mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	Merge branch 'access' of github.com:gogits/gogs into dev
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
[run]
 | 
					[run]
 | 
				
			||||||
init_cmds = [
 | 
					init_cmds = [
 | 
				
			||||||
	["grep", "-rn", "FIXME", "."],
 | 
						#["grep", "-rn", "FIXME", "."],
 | 
				
			||||||
	["./gogs", "web"]
 | 
						["./gogs", "web"]
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
watch_all = true
 | 
					watch_all = true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,13 +7,13 @@ Gogs (Go Git Service) is a painless self-hosted Git service written in Go.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Current version: 0.5.13 Beta
 | 
					##### Current version: 0.5.16 Beta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### NOTICES
 | 
					### NOTICES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
 | 
					- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
 | 
				
			||||||
- The demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch.
 | 
					- The demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch.
 | 
				
			||||||
- You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing a issue or making a Pull Request.
 | 
					- You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing an issue or making a Pull Request.
 | 
				
			||||||
- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**.  Thanks!
 | 
					- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**.  Thanks!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Other language version
 | 
					#### Other language version
 | 
				
			||||||
@@ -57,7 +57,7 @@ The goal of this project is to make the easiest, fastest, and most painless way
 | 
				
			|||||||
## System Requirements
 | 
					## System Requirements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- A cheap Raspberry Pi is powerful enough for basic functionality.
 | 
					- A cheap Raspberry Pi is powerful enough for basic functionality.
 | 
				
			||||||
- At least 4 CPU cores and 1GB RAM would be the baseline for teamwork.
 | 
					- At least 2 CPU cores and 1GB RAM would be the baseline for teamwork.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务。
 | 
				
			|||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### 当前版本:0.5.13 Beta
 | 
					##### 当前版本:0.5.16 Beta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 开发目的
 | 
					## 开发目的
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +44,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
 | 
				
			|||||||
## 系统要求
 | 
					## 系统要求
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- 最低的系统硬件要求为一个廉价的树莓派
 | 
					- 最低的系统硬件要求为一个廉价的树莓派
 | 
				
			||||||
- 如果用于团队项目,建议使用 4 核 CPU 及 1GB 内存
 | 
					- 如果用于团队项目,建议使用 2 核 CPU 及 1GB 内存
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 安装部署
 | 
					## 安装部署
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										59
									
								
								cmd/serve.go
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								cmd/serve.go
									
									
									
									
									
								
							@@ -8,7 +8,6 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -43,7 +42,7 @@ func setup(logPath string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	models.LoadModelsConfig()
 | 
						models.LoadModelsConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if models.UseSQLite3 {
 | 
						if setting.UseSQLite3 {
 | 
				
			||||||
		workDir, _ := setting.WorkDir()
 | 
							workDir, _ := setting.WorkDir()
 | 
				
			||||||
		os.Chdir(workDir)
 | 
							os.Chdir(workDir)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -67,33 +66,33 @@ func parseCmd(cmd string) (string, string) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	COMMANDS_READONLY = map[string]models.AccessType{
 | 
						COMMANDS_READONLY = map[string]models.AccessMode{
 | 
				
			||||||
		"git-upload-pack":    models.WRITABLE,
 | 
							"git-upload-pack":    models.ACCESS_MODE_WRITE,
 | 
				
			||||||
		"git upload-pack":    models.WRITABLE,
 | 
							"git upload-pack":    models.ACCESS_MODE_WRITE,
 | 
				
			||||||
		"git-upload-archive": models.WRITABLE,
 | 
							"git-upload-archive": models.ACCESS_MODE_WRITE,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	COMMANDS_WRITE = map[string]models.AccessType{
 | 
						COMMANDS_WRITE = map[string]models.AccessMode{
 | 
				
			||||||
		"git-receive-pack": models.READABLE,
 | 
							"git-receive-pack": models.ACCESS_MODE_READ,
 | 
				
			||||||
		"git receive-pack": models.READABLE,
 | 
							"git receive-pack": models.ACCESS_MODE_READ,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func In(b string, sl map[string]models.AccessType) bool {
 | 
					func In(b string, sl map[string]models.AccessMode) bool {
 | 
				
			||||||
	_, e := sl[b]
 | 
						_, e := sl[b]
 | 
				
			||||||
	return e
 | 
						return e
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func runServ(k *cli.Context) {
 | 
					func runServ(c *cli.Context) {
 | 
				
			||||||
	if k.IsSet("config") {
 | 
						if c.IsSet("config") {
 | 
				
			||||||
		setting.CustomConf = k.String("config")
 | 
							setting.CustomConf = c.String("config")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	setup("serv.log")
 | 
						setup("serv.log")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(k.Args()) < 1 {
 | 
						if len(c.Args()) < 1 {
 | 
				
			||||||
		log.GitLogger.Fatal(2, "Not enough arguments")
 | 
							log.GitLogger.Fatal(2, "Not enough arguments")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	keys := strings.Split(k.Args()[0], "-")
 | 
						keys := strings.Split(c.Args()[0], "-")
 | 
				
			||||||
	if len(keys) != 2 {
 | 
						if len(keys) != 2 {
 | 
				
			||||||
		println("Gogs: auth file format error")
 | 
							println("Gogs: auth file format error")
 | 
				
			||||||
		log.GitLogger.Fatal(2, "Invalid auth file format: %s", os.Args[2])
 | 
							log.GitLogger.Fatal(2, "Invalid auth file format: %s", os.Args[2])
 | 
				
			||||||
@@ -117,6 +116,7 @@ func runServ(k *cli.Context) {
 | 
				
			|||||||
	cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
 | 
						cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
 | 
				
			||||||
	if cmd == "" {
 | 
						if cmd == "" {
 | 
				
			||||||
		println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
 | 
							println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
 | 
				
			||||||
 | 
							println("If this is what you do not expect, please log in with password and setup Gogs under another user.")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,17 +144,6 @@ func runServ(k *cli.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Access check.
 | 
						// Access check.
 | 
				
			||||||
	switch {
 | 
					 | 
				
			||||||
	case isWrite:
 | 
					 | 
				
			||||||
		has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.WRITABLE)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			println("Gogs: internal error:", err.Error())
 | 
					 | 
				
			||||||
			log.GitLogger.Fatal(2, "Fail to check write access:", err)
 | 
					 | 
				
			||||||
		} else if !has {
 | 
					 | 
				
			||||||
			println("You have no right to write this repository")
 | 
					 | 
				
			||||||
			log.GitLogger.Fatal(2, "User %s has no right to write repository %s", user.Name, repoPath)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case isRead:
 | 
					 | 
				
			||||||
	repo, err := models.GetRepositoryByName(repoUser.Id, repoName)
 | 
						repo, err := models.GetRepositoryByName(repoUser.Id, repoName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if err == models.ErrRepoNotExist {
 | 
							if err == models.ErrRepoNotExist {
 | 
				
			||||||
@@ -165,11 +154,27 @@ func runServ(k *cli.Context) {
 | 
				
			|||||||
		log.GitLogger.Fatal(2, "Fail to get repository: %v", err)
 | 
							log.GitLogger.Fatal(2, "Fail to get repository: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case isWrite:
 | 
				
			||||||
 | 
							has, err := models.HasAccess(user, repo, models.ACCESS_MODE_WRITE)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								println("Gogs: internal error:", err.Error())
 | 
				
			||||||
 | 
								log.GitLogger.Fatal(2, "Fail to check write access:", err)
 | 
				
			||||||
 | 
							} else if !has {
 | 
				
			||||||
 | 
								println("You have no right to write this repository")
 | 
				
			||||||
 | 
								log.GitLogger.Fatal(2, "User %s has no right to write repository %s", user.Name, repoPath)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if repo.IsMirror {
 | 
				
			||||||
 | 
								println("You can't write to a mirror repository")
 | 
				
			||||||
 | 
								log.GitLogger.Fatal(2, "User %s tried to write to a mirror repository %s", user.Name, repoPath)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case isRead:
 | 
				
			||||||
		if !repo.IsPrivate {
 | 
							if !repo.IsPrivate {
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.READABLE)
 | 
							has, err := models.HasAccess(user, repo, models.ACCESS_MODE_READ)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			println("Gogs: internal error:", err.Error())
 | 
								println("Gogs: internal error:", err.Error())
 | 
				
			||||||
			log.GitLogger.Fatal(2, "Fail to check read access:", err)
 | 
								log.GitLogger.Fatal(2, "Fail to check read access:", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -318,7 +318,7 @@ func runWeb(ctx *cli.Context) {
 | 
				
			|||||||
		m.Get("/template/*", dev.TemplatePreview)
 | 
							m.Get("/template/*", dev.TemplatePreview)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reqTrueOwner := middleware.RequireTrueOwner()
 | 
						reqAdmin := middleware.RequireAdmin()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Organization.
 | 
						// Organization.
 | 
				
			||||||
	m.Group("/org", func() {
 | 
						m.Group("/org", func() {
 | 
				
			||||||
@@ -393,7 +393,7 @@ func runWeb(ctx *cli.Context) {
 | 
				
			|||||||
				m.Post("/:name", repo.GitHooksEditPost)
 | 
									m.Post("/:name", repo.GitHooksEditPost)
 | 
				
			||||||
			}, middleware.GitHookService())
 | 
								}, middleware.GitHookService())
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner)
 | 
						}, reqSignIn, middleware.RepoAssignment(true), reqAdmin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Group("/:username/:reponame", func() {
 | 
						m.Group("/:username/:reponame", func() {
 | 
				
			||||||
		m.Get("/action/:action", repo.Action)
 | 
							m.Get("/action/:action", repo.Action)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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.5.14.0222 Beta"
 | 
					const APP_VER = "0.5.16.0228 Beta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	runtime.GOMAXPROCS(runtime.NumCPU())
 | 
						runtime.GOMAXPROCS(runtime.NumCPU())
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										216
									
								
								models/access.go
									
									
									
									
									
								
							
							
						
						
									
										216
									
								
								models/access.go
									
									
									
									
									
								
							@@ -5,76 +5,190 @@
 | 
				
			|||||||
package models
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"strings"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AccessType int
 | 
					type AccessMode int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	READABLE AccessType = iota + 1
 | 
						ACCESS_MODE_NONE AccessMode = iota
 | 
				
			||||||
	WRITABLE
 | 
						ACCESS_MODE_READ
 | 
				
			||||||
 | 
						ACCESS_MODE_WRITE
 | 
				
			||||||
 | 
						ACCESS_MODE_ADMIN
 | 
				
			||||||
 | 
						ACCESS_MODE_OWNER
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Access represents the accessibility of user to repository.
 | 
					// Access represents the highest access level of a user to the repository. The only access type
 | 
				
			||||||
 | 
					// that is not in this table is the real owner of a repository. In case of an organization
 | 
				
			||||||
 | 
					// repository, the members of the owners team are in this table.
 | 
				
			||||||
type Access struct {
 | 
					type Access struct {
 | 
				
			||||||
	Id       int64
 | 
						ID     int64 `xorm:"pk autoincr"`
 | 
				
			||||||
	UserName string     `xorm:"UNIQUE(s)"`
 | 
						UserID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
	RepoName string     `xorm:"UNIQUE(s)"` // <user name>/<repo name>
 | 
						RepoID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
	Mode     AccessType `xorm:"UNIQUE(s)"`
 | 
						Mode   AccessMode
 | 
				
			||||||
	Created  time.Time  `xorm:"CREATED"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddAccess adds new access record.
 | 
					func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
 | 
				
			||||||
func AddAccess(access *Access) error {
 | 
						mode := ACCESS_MODE_NONE
 | 
				
			||||||
	access.UserName = strings.ToLower(access.UserName)
 | 
						if !repo.IsPrivate {
 | 
				
			||||||
	access.RepoName = strings.ToLower(access.RepoName)
 | 
							mode = ACCESS_MODE_READ
 | 
				
			||||||
	_, err := x.Insert(access)
 | 
						}
 | 
				
			||||||
	return err
 | 
					
 | 
				
			||||||
 | 
						if u != nil {
 | 
				
			||||||
 | 
							if u.Id == repo.OwnerId {
 | 
				
			||||||
 | 
								return ACCESS_MODE_OWNER, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							a := &Access{UserID: u.Id, RepoID: repo.Id}
 | 
				
			||||||
 | 
							if has, err := e.Get(a); !has || err != nil {
 | 
				
			||||||
 | 
								return mode, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return a.Mode, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mode, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateAccess updates access information.
 | 
					// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
 | 
				
			||||||
func UpdateAccess(access *Access) error {
 | 
					// user does not have access. User can be nil!
 | 
				
			||||||
	access.UserName = strings.ToLower(access.UserName)
 | 
					func AccessLevel(u *User, repo *Repository) (AccessMode, error) {
 | 
				
			||||||
	access.RepoName = strings.ToLower(access.RepoName)
 | 
						return accessLevel(x, u, repo)
 | 
				
			||||||
	_, err := x.Id(access.Id).Update(access)
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteAccess deletes access record.
 | 
					func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) {
 | 
				
			||||||
func DeleteAccess(access *Access) error {
 | 
						mode, err := accessLevel(e, u, repo)
 | 
				
			||||||
	_, err := x.Delete(access)
 | 
						return testMode <= mode, err
 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateAccess updates access information with session for rolling back.
 | 
					// HasAccess returns true if someone has the request access level. User can be nil!
 | 
				
			||||||
func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
 | 
					func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) {
 | 
				
			||||||
	if _, err := sess.Id(access.Id).Update(access); err != nil {
 | 
						return hasAccess(x, u, repo, testMode)
 | 
				
			||||||
		sess.Rollback()
 | 
					}
 | 
				
			||||||
		return err
 | 
					
 | 
				
			||||||
 | 
					// GetAccessibleRepositories finds all repositories where a user has access to,
 | 
				
			||||||
 | 
					// besides his own.
 | 
				
			||||||
 | 
					func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
 | 
				
			||||||
 | 
						accesses := make([]*Access, 0, 10)
 | 
				
			||||||
 | 
						if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repos := make(map[*Repository]AccessMode, len(accesses))
 | 
				
			||||||
 | 
						for _, access := range accesses {
 | 
				
			||||||
 | 
							repo, err := GetRepositoryById(access.RepoID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err = repo.GetOwner(); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							} else if repo.OwnerId == u.Id {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							repos[repo] = access.Mode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// FIXME: should we generate an ordered list here? Random looks weird.
 | 
				
			||||||
 | 
						return repos, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func maxAccessMode(modes ...AccessMode) AccessMode {
 | 
				
			||||||
 | 
						max := ACCESS_MODE_NONE
 | 
				
			||||||
 | 
						for _, mode := range modes {
 | 
				
			||||||
 | 
							if mode > max {
 | 
				
			||||||
 | 
								max = mode
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return max
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FIXME: do corss-comparison so reduce deletions and additions to the minimum?
 | 
				
			||||||
 | 
					func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode) (err error) {
 | 
				
			||||||
 | 
						minMode := ACCESS_MODE_READ
 | 
				
			||||||
 | 
						if !repo.IsPrivate {
 | 
				
			||||||
 | 
							minMode = ACCESS_MODE_WRITE
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newAccesses := make([]Access, 0, len(accessMap))
 | 
				
			||||||
 | 
						for userID, mode := range accessMap {
 | 
				
			||||||
 | 
							if mode < minMode {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							newAccesses = append(newAccesses, Access{
 | 
				
			||||||
 | 
								UserID: userID,
 | 
				
			||||||
 | 
								RepoID: repo.Id,
 | 
				
			||||||
 | 
								Mode:   mode,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete old accesses and insert new ones for repository.
 | 
				
			||||||
 | 
						if _, err = e.Delete(&Access{RepoID: repo.Id}); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("delete old accesses: %v", err)
 | 
				
			||||||
 | 
						} else if _, err = e.Insert(newAccesses); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("insert new accesses: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasAccess returns true if someone can read or write to given repository.
 | 
					// FIXME: should be able to have read-only access.
 | 
				
			||||||
// The repoName should be in format <username>/<reponame>.
 | 
					// Give all collaborators write access.
 | 
				
			||||||
func HasAccess(uname, repoName string, mode AccessType) (bool, error) {
 | 
					func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]AccessMode) error {
 | 
				
			||||||
	if len(repoName) == 0 {
 | 
						collaborators, err := repo.getCollaborators(e)
 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	access := &Access{
 | 
					 | 
				
			||||||
		UserName: strings.ToLower(uname),
 | 
					 | 
				
			||||||
		RepoName: strings.ToLower(repoName),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	has, err := x.Get(access)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return false, err
 | 
							return fmt.Errorf("getCollaborators: %v", err)
 | 
				
			||||||
	} else if !has {
 | 
					 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	} else if mode > access.Mode {
 | 
					 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true, nil
 | 
						for _, c := range collaborators {
 | 
				
			||||||
 | 
							accessMap[c.Id] = ACCESS_MODE_WRITE
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// recalculateTeamAccesses recalculates new accesses for teams of an organization
 | 
				
			||||||
 | 
					// except the team whose ID is given. It is used to assign a team ID when
 | 
				
			||||||
 | 
					// remove repository from that team.
 | 
				
			||||||
 | 
					func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err error) {
 | 
				
			||||||
 | 
						accessMap := make(map[int64]AccessMode, 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = repo.refreshCollaboratorAccesses(e, accessMap); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = repo.getOwner(e); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if repo.Owner.IsOrganization() {
 | 
				
			||||||
 | 
							if err = repo.Owner.getTeams(e); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, t := range repo.Owner.Teams {
 | 
				
			||||||
 | 
								if t.ID == ignTeamID {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if t.IsOwnerTeam() {
 | 
				
			||||||
 | 
									t.Authorize = ACCESS_MODE_OWNER
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if err = t.getMembers(e); err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("getMembers '%d': %v", t.ID, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, m := range t.Members {
 | 
				
			||||||
 | 
									accessMap[m.Id] = maxAccessMode(accessMap[m.Id], t.Authorize)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return repo.refreshAccesses(e, accessMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (repo *Repository) recalculateAccesses(e Engine) error {
 | 
				
			||||||
 | 
						accessMap := make(map[int64]AccessMode, 20)
 | 
				
			||||||
 | 
						if err := repo.refreshCollaboratorAccesses(e, accessMap); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return repo.refreshAccesses(e, accessMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RecalculateAccesses recalculates all accesses for repository.
 | 
				
			||||||
 | 
					func (r *Repository) RecalculateAccesses() error {
 | 
				
			||||||
 | 
						return r.recalculateAccesses(x)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -434,46 +434,58 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewRepoAction adds new action for creating repository.
 | 
					func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
 | 
				
			||||||
func NewRepoAction(u *User, repo *Repository) (err error) {
 | 
						if err = notifyWatchers(e, &Action{
 | 
				
			||||||
	if err = NotifyWatchers(&Action{ActUserId: u.Id, ActUserName: u.Name, ActEmail: u.Email,
 | 
							ActUserId:    u.Id,
 | 
				
			||||||
		OpType: CREATE_REPO, RepoId: repo.Id, RepoUserName: repo.Owner.Name, RepoName: repo.Name,
 | 
							ActUserName:  u.Name,
 | 
				
			||||||
 | 
							ActEmail:     u.Email,
 | 
				
			||||||
 | 
							OpType:       CREATE_REPO,
 | 
				
			||||||
 | 
							RepoId:       repo.Id,
 | 
				
			||||||
 | 
							RepoUserName: repo.Owner.Name,
 | 
				
			||||||
 | 
							RepoName:     repo.Name,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate}); err != nil {
 | 
							IsPrivate:    repo.IsPrivate}); err != nil {
 | 
				
			||||||
		log.Error(4, "NotifyWatchers: %d/%s", u.Id, repo.Name)
 | 
							return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id)
 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("action.NewRepoAction: %s/%s", u.Name, repo.Name)
 | 
						log.Trace("action.NewRepoAction: %s/%s", u.Name, repo.Name)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TransferRepoAction adds new action for transferring repository.
 | 
					// NewRepoAction adds new action for creating repository.
 | 
				
			||||||
func TransferRepoAction(u, newUser *User, repo *Repository) (err error) {
 | 
					func NewRepoAction(u *User, repo *Repository) (err error) {
 | 
				
			||||||
 | 
						return newRepoAction(x, u, repo)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
 | 
				
			||||||
	action := &Action{
 | 
						action := &Action{
 | 
				
			||||||
		ActUserId:    u.Id,
 | 
							ActUserId:    actUser.Id,
 | 
				
			||||||
		ActUserName:  u.Name,
 | 
							ActUserName:  actUser.Name,
 | 
				
			||||||
		ActEmail:     u.Email,
 | 
							ActEmail:     actUser.Email,
 | 
				
			||||||
		OpType:       TRANSFER_REPO,
 | 
							OpType:       TRANSFER_REPO,
 | 
				
			||||||
		RepoId:       repo.Id,
 | 
							RepoId:       repo.Id,
 | 
				
			||||||
		RepoUserName: newUser.Name,
 | 
							RepoUserName: newOwner.Name,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							RepoName:     repo.Name,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
							IsPrivate:    repo.IsPrivate,
 | 
				
			||||||
		Content:      path.Join(repo.Owner.LowerName, repo.LowerName),
 | 
							Content:      path.Join(oldOwner.LowerName, repo.LowerName),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err = NotifyWatchers(action); err != nil {
 | 
						if err = notifyWatchers(e, action); err != nil {
 | 
				
			||||||
		log.Error(4, "NotifyWatchers: %d/%s", u.Id, repo.Name)
 | 
							return fmt.Errorf("notify watchers '%d/%s'", actUser.Id, repo.Id)
 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Remove watch for organization.
 | 
						// Remove watch for organization.
 | 
				
			||||||
	if repo.Owner.IsOrganization() {
 | 
						if repo.Owner.IsOrganization() {
 | 
				
			||||||
		if err = WatchRepo(repo.Owner.Id, repo.Id, false); err != nil {
 | 
							if err = watchRepo(e, repo.Owner.Id, repo.Id, false); err != nil {
 | 
				
			||||||
			log.Error(4, "WatchRepo", err)
 | 
								return fmt.Errorf("watch repository: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("action.TransferRepoAction: %s/%s", u.Name, repo.Name)
 | 
						log.Trace("action.TransferRepoAction: %s/%s", actUser.Name, repo.Name)
 | 
				
			||||||
	return err
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TransferRepoAction adds new action for transferring repository.
 | 
				
			||||||
 | 
					func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
 | 
				
			||||||
 | 
						return transferRepoAction(x, actUser, oldOwner, newOwner, repo)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetFeeds returns action list of given user in given context.
 | 
					// GetFeeds returns action list of given user in given context.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,30 +282,33 @@ type IssueUser struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewIssueUserPairs adds new issue-user pairs for new issue of repository.
 | 
					// NewIssueUserPairs adds new issue-user pairs for new issue of repository.
 | 
				
			||||||
func NewIssueUserPairs(rid, iid, oid, pid, aid int64, repoName string) (err error) {
 | 
					func NewIssueUserPairs(repo *Repository, issueID, orgID, posterID, assigneeID int64) (err error) {
 | 
				
			||||||
	iu := &IssueUser{IssueId: iid, RepoId: rid}
 | 
						users, err := repo.GetCollaborators()
 | 
				
			||||||
 | 
					 | 
				
			||||||
	us, err := GetCollaborators(repoName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iu := &IssueUser{
 | 
				
			||||||
 | 
							IssueId: issueID,
 | 
				
			||||||
 | 
							RepoId:  repo.Id,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isNeedAddPoster := true
 | 
						isNeedAddPoster := true
 | 
				
			||||||
	for _, u := range us {
 | 
						for _, u := range users {
 | 
				
			||||||
		iu.Uid = u.Id
 | 
							iu.Uid = u.Id
 | 
				
			||||||
		iu.IsPoster = iu.Uid == pid
 | 
							iu.IsPoster = iu.Uid == posterID
 | 
				
			||||||
		if isNeedAddPoster && iu.IsPoster {
 | 
							if isNeedAddPoster && iu.IsPoster {
 | 
				
			||||||
			isNeedAddPoster = false
 | 
								isNeedAddPoster = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		iu.IsAssigned = iu.Uid == aid
 | 
							iu.IsAssigned = iu.Uid == assigneeID
 | 
				
			||||||
		if _, err = x.Insert(iu); err != nil {
 | 
							if _, err = x.Insert(iu); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if isNeedAddPoster {
 | 
						if isNeedAddPoster {
 | 
				
			||||||
		iu.Uid = pid
 | 
							iu.Uid = posterID
 | 
				
			||||||
		iu.IsPoster = true
 | 
							iu.IsPoster = true
 | 
				
			||||||
		iu.IsAssigned = iu.Uid == aid
 | 
							iu.IsAssigned = iu.Uid == assigneeID
 | 
				
			||||||
		if _, err = x.Insert(iu); err != nil {
 | 
							if _, err = x.Insert(iu); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,44 @@
 | 
				
			|||||||
 | 
					// Copyright 2015 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 migrations
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type migration func(*xorm.Engine) error
 | 
					const _MIN_DB_VER = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Migration interface {
 | 
				
			||||||
 | 
						Description() string
 | 
				
			||||||
 | 
						Migrate(*xorm.Engine) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type migration struct {
 | 
				
			||||||
 | 
						description string
 | 
				
			||||||
 | 
						migrate     func(*xorm.Engine) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewMigration(desc string, fn func(*xorm.Engine) error) Migration {
 | 
				
			||||||
 | 
						return &migration{desc, fn}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *migration) Description() string {
 | 
				
			||||||
 | 
						return m.description
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *migration) Migrate(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						return m.migrate(x)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The version table. Should have only one row with id==1
 | 
					// The version table. Should have only one row with id==1
 | 
				
			||||||
type Version struct {
 | 
					type Version struct {
 | 
				
			||||||
@@ -15,30 +47,55 @@ type Version struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is a sequence of migrations. Add new migrations to the bottom of the list.
 | 
					// This is a sequence of migrations. Add new migrations to the bottom of the list.
 | 
				
			||||||
// If you want to "retire" a migration, replace it with "expiredMigration"
 | 
					// If you want to "retire" a migration, remove it from the top of the list and
 | 
				
			||||||
var migrations = []migration{}
 | 
					// update _MIN_VER_DB accordingly
 | 
				
			||||||
 | 
					var migrations = []Migration{
 | 
				
			||||||
 | 
						NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1
 | 
				
			||||||
 | 
						NewMigration("make authorize 4 if team is owners", ownerTeamUpdate),       // V1 -> V2
 | 
				
			||||||
 | 
						NewMigration("refactor access table to use id's", accessRefactor),         // V2 -> V3
 | 
				
			||||||
 | 
						NewMigration("generate team-repo from team", teamToTeamRepo),              // V3 -> V4
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Migrate database to current version
 | 
					// Migrate database to current version
 | 
				
			||||||
func Migrate(x *xorm.Engine) error {
 | 
					func Migrate(x *xorm.Engine) error {
 | 
				
			||||||
	if err := x.Sync(new(Version)); err != nil {
 | 
						if err := x.Sync(new(Version)); err != nil {
 | 
				
			||||||
		return err
 | 
							return fmt.Errorf("sync: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	currentVersion := &Version{Id: 1}
 | 
						currentVersion := &Version{Id: 1}
 | 
				
			||||||
	has, err := x.Get(currentVersion)
 | 
						has, err := x.Get(currentVersion)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return fmt.Errorf("get: %v", err)
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
		if _, err = x.InsertOne(currentVersion); err != nil {
 | 
							// If the user table does not exist it is a fresh installation and we
 | 
				
			||||||
 | 
							// can skip all migrations.
 | 
				
			||||||
 | 
							needsMigration, err := x.IsTableExist("user")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if needsMigration {
 | 
				
			||||||
 | 
								isEmpty, err := x.IsTableEmpty("user")
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// If the user table is empty it is a fresh installation and we can
 | 
				
			||||||
 | 
								// skip all migrations.
 | 
				
			||||||
 | 
								needsMigration = !isEmpty
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !needsMigration {
 | 
				
			||||||
 | 
								currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if _, err = x.InsertOne(currentVersion); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("insert: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v := currentVersion.Version
 | 
						v := currentVersion.Version
 | 
				
			||||||
 | 
						for i, m := range migrations[v-_MIN_DB_VER:] {
 | 
				
			||||||
	for i, migration := range migrations[v:] {
 | 
							log.Info("Migration: %s", m.Description())
 | 
				
			||||||
		if err = migration(x); err != nil {
 | 
							if err = m.Migrate(x); err != nil {
 | 
				
			||||||
			return err
 | 
								return fmt.Errorf("do migrate: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		currentVersion.Version = v + int64(i) + 1
 | 
							currentVersion.Version = v + int64(i) + 1
 | 
				
			||||||
		if _, err = x.Id(1).Update(currentVersion); err != nil {
 | 
							if _, err = x.Id(1).Update(currentVersion); err != nil {
 | 
				
			||||||
@@ -48,6 +105,267 @@ func Migrate(x *xorm.Engine) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func expiredMigration(x *xorm.Engine) error {
 | 
					func sessionRelease(sess *xorm.Session) {
 | 
				
			||||||
	return errors.New("You are migrating from a too old gogs version")
 | 
						if !sess.IsCommitedOrRollbacked {
 | 
				
			||||||
 | 
							sess.Rollback()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sess.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func accessToCollaboration(x *xorm.Engine) (err error) {
 | 
				
			||||||
 | 
						type Collaboration struct {
 | 
				
			||||||
 | 
							ID      int64 `xorm:"pk autoincr"`
 | 
				
			||||||
 | 
							RepoID  int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
 | 
				
			||||||
 | 
							UserID  int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
 | 
				
			||||||
 | 
							Created time.Time
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = x.Sync(new(Collaboration)); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("sync: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						results, err := x.Query("SELECT u.id AS `uid`, a.repo_name AS `repo`, a.mode AS `mode`, a.created as `created` FROM `access` a JOIN `user` u ON a.user_name=u.lower_name")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sessionRelease(sess)
 | 
				
			||||||
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						offset := strings.Split(time.Now().String(), " ")[2]
 | 
				
			||||||
 | 
						for _, result := range results {
 | 
				
			||||||
 | 
							mode := com.StrTo(result["mode"]).MustInt64()
 | 
				
			||||||
 | 
							// Collaborators must have write access.
 | 
				
			||||||
 | 
							if mode < 2 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							userID := com.StrTo(result["uid"]).MustInt64()
 | 
				
			||||||
 | 
							repoRefName := string(result["repo"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var created time.Time
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case setting.UseSQLite3:
 | 
				
			||||||
 | 
								created, _ = time.Parse(time.RFC3339, string(result["created"]))
 | 
				
			||||||
 | 
							case setting.UseMySQL:
 | 
				
			||||||
 | 
								created, _ = time.Parse("2006-01-02 15:04:05-0700", string(result["created"])+offset)
 | 
				
			||||||
 | 
							case setting.UsePostgreSQL:
 | 
				
			||||||
 | 
								created, _ = time.Parse("2006-01-02T15:04:05Z-0700", string(result["created"])+offset)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// find owner of repository
 | 
				
			||||||
 | 
							parts := strings.SplitN(repoRefName, "/", 2)
 | 
				
			||||||
 | 
							ownerName := parts[0]
 | 
				
			||||||
 | 
							repoName := parts[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							results, err := sess.Query("SELECT u.id as `uid`, ou.uid as `memberid` FROM `user` u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?", ownerName)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(results) < 1 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ownerID := com.StrTo(results[0]["uid"]).MustInt64()
 | 
				
			||||||
 | 
							if ownerID == userID {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// test if user is member of owning organization
 | 
				
			||||||
 | 
							isMember := false
 | 
				
			||||||
 | 
							for _, member := range results {
 | 
				
			||||||
 | 
								memberID := com.StrTo(member["memberid"]).MustInt64()
 | 
				
			||||||
 | 
								// We can skip all cases that a user is member of the owning organization
 | 
				
			||||||
 | 
								if memberID == userID {
 | 
				
			||||||
 | 
									isMember = true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if isMember {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							results, err = sess.Query("SELECT id FROM `repository` WHERE owner_id=? AND lower_name=?", ownerID, repoName)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if len(results) < 1 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							collaboration := &Collaboration{
 | 
				
			||||||
 | 
								UserID: userID,
 | 
				
			||||||
 | 
								RepoID: com.StrTo(results[0]["id"]).MustInt64(),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							has, err := sess.Get(collaboration)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							} else if has {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							collaboration.Created = created
 | 
				
			||||||
 | 
							if _, err = sess.InsertOne(collaboration); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ownerTeamUpdate(x *xorm.Engine) (err error) {
 | 
				
			||||||
 | 
						if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("update owner team table: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func accessRefactor(x *xorm.Engine) (err error) {
 | 
				
			||||||
 | 
						type (
 | 
				
			||||||
 | 
							AccessMode int
 | 
				
			||||||
 | 
							Access     struct {
 | 
				
			||||||
 | 
								ID     int64 `xorm:"pk autoincr"`
 | 
				
			||||||
 | 
								UserID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
								RepoID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
								Mode   AccessMode
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							UserRepo struct {
 | 
				
			||||||
 | 
								UserID int64
 | 
				
			||||||
 | 
								RepoID int64
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We consiously don't start a session yet as we make only reads for now, no writes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accessMap := make(map[UserRepo]AccessMode, 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("select repositories: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, repo := range results {
 | 
				
			||||||
 | 
							repoID := com.StrTo(repo["repo_id"]).MustInt64()
 | 
				
			||||||
 | 
							isPrivate := com.StrTo(repo["is_private"]).MustInt() > 0
 | 
				
			||||||
 | 
							ownerID := com.StrTo(repo["owner_id"]).MustInt64()
 | 
				
			||||||
 | 
							ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("select collaborators: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, user := range results {
 | 
				
			||||||
 | 
								userID := com.StrTo(user["user_id"]).MustInt64()
 | 
				
			||||||
 | 
								accessMap[UserRepo{userID, repoID}] = 2 // WRITE ACCESS
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !ownerIsOrganization {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// The minimum level to add a new access record,
 | 
				
			||||||
 | 
							// because public repository has implicit open access.
 | 
				
			||||||
 | 
							minAccessLevel := AccessMode(0)
 | 
				
			||||||
 | 
							if !isPrivate {
 | 
				
			||||||
 | 
								minAccessLevel = 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							repoString := "$" + string(repo["repo_id"]) + "|"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("select teams from org: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, team := range results {
 | 
				
			||||||
 | 
								if !strings.Contains(string(team["repo_ids"]), repoString) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								teamID := com.StrTo(team["id"]).MustInt64()
 | 
				
			||||||
 | 
								mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("select users from team: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, user := range results {
 | 
				
			||||||
 | 
									userID := com.StrTo(user["user_id"]).MustInt64()
 | 
				
			||||||
 | 
									accessMap[UserRepo{userID, repoID}] = mode
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Drop table can't be in a session (at least not in sqlite)
 | 
				
			||||||
 | 
						if _, err = x.Exec("DROP TABLE `access`"); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("drop access table: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now we start writing so we make a session
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sessionRelease(sess)
 | 
				
			||||||
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = sess.Sync2(new(Access)); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("sync: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accesses := make([]*Access, 0, len(accessMap))
 | 
				
			||||||
 | 
						for ur, mode := range accessMap {
 | 
				
			||||||
 | 
							accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Insert(accesses); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("insert accesses: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func teamToTeamRepo(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						type TeamRepo struct {
 | 
				
			||||||
 | 
							ID     int64 `xorm:"pk autoincr"`
 | 
				
			||||||
 | 
							OrgID  int64 `xorm:"INDEX"`
 | 
				
			||||||
 | 
							TeamID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
							RepoID int64 `xorm:"UNIQUE(s)"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						teamRepos := make([]*TeamRepo, 0, 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("select teams: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, team := range results {
 | 
				
			||||||
 | 
							orgID := com.StrTo(team["org_id"]).MustInt64()
 | 
				
			||||||
 | 
							teamID := com.StrTo(team["id"]).MustInt64()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
 | 
				
			||||||
 | 
								repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
 | 
				
			||||||
 | 
								if repoID == 0 {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								teamRepos = append(teamRepos, &TeamRepo{
 | 
				
			||||||
 | 
									OrgID:  orgID,
 | 
				
			||||||
 | 
									TeamID: teamID,
 | 
				
			||||||
 | 
									RepoID: repoID,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sessionRelease(sess)
 | 
				
			||||||
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = sess.Sync2(new(TeamRepo)); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("sync: %v", err)
 | 
				
			||||||
 | 
						} else if _, err = sess.Insert(teamRepos); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("insert team-repos: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,10 +12,11 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ "github.com/go-sql-driver/mysql"
 | 
						_ "github.com/go-sql-driver/mysql"
 | 
				
			||||||
 | 
						"github.com/go-xorm/core"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
	_ "github.com/lib/pq"
 | 
						_ "github.com/lib/pq"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// "github.com/gogits/gogs/models/migrations"
 | 
						"github.com/gogits/gogs/models/migrations"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/setting"
 | 
						"github.com/gogits/gogs/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,12 +24,22 @@ import (
 | 
				
			|||||||
type Engine interface {
 | 
					type Engine interface {
 | 
				
			||||||
	Delete(interface{}) (int64, error)
 | 
						Delete(interface{}) (int64, error)
 | 
				
			||||||
	Exec(string, ...interface{}) (sql.Result, error)
 | 
						Exec(string, ...interface{}) (sql.Result, error)
 | 
				
			||||||
 | 
						Find(interface{}, ...interface{}) error
 | 
				
			||||||
	Get(interface{}) (bool, error)
 | 
						Get(interface{}) (bool, error)
 | 
				
			||||||
	Insert(...interface{}) (int64, error)
 | 
						Insert(...interface{}) (int64, error)
 | 
				
			||||||
 | 
						InsertOne(interface{}) (int64, error)
 | 
				
			||||||
	Id(interface{}) *xorm.Session
 | 
						Id(interface{}) *xorm.Session
 | 
				
			||||||
 | 
						Sql(string, ...interface{}) *xorm.Session
 | 
				
			||||||
	Where(string, ...interface{}) *xorm.Session
 | 
						Where(string, ...interface{}) *xorm.Session
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sessionRelease(sess *xorm.Session) {
 | 
				
			||||||
 | 
						if !sess.IsCommitedOrRollbacked {
 | 
				
			||||||
 | 
							sess.Rollback()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sess.Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	x         *xorm.Engine
 | 
						x         *xorm.Engine
 | 
				
			||||||
	tables    []interface{}
 | 
						tables    []interface{}
 | 
				
			||||||
@@ -39,24 +50,30 @@ var (
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EnableSQLite3 bool
 | 
						EnableSQLite3 bool
 | 
				
			||||||
	UseSQLite3    bool
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	tables = append(tables,
 | 
						tables = append(tables,
 | 
				
			||||||
		new(User), new(PublicKey), new(Follow), new(Oauth2), new(AccessToken),
 | 
							new(User), new(PublicKey), new(Oauth2), new(AccessToken),
 | 
				
			||||||
		new(Repository), new(Watch), new(Star), new(Action), new(Access),
 | 
							new(Repository), new(Collaboration), new(Access),
 | 
				
			||||||
 | 
							new(Watch), new(Star), new(Follow), new(Action),
 | 
				
			||||||
		new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
 | 
							new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
 | 
				
			||||||
		new(Mirror), new(Release), new(LoginSource), new(Webhook),
 | 
							new(Mirror), new(Release), new(LoginSource), new(Webhook),
 | 
				
			||||||
		new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
 | 
							new(UpdateTask), new(HookTask),
 | 
				
			||||||
 | 
							new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
 | 
				
			||||||
		new(Notice), new(EmailAddress))
 | 
							new(Notice), new(EmailAddress))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func LoadModelsConfig() {
 | 
					func LoadModelsConfig() {
 | 
				
			||||||
	sec := setting.Cfg.Section("database")
 | 
						sec := setting.Cfg.Section("database")
 | 
				
			||||||
	DbCfg.Type = sec.Key("DB_TYPE").String()
 | 
						DbCfg.Type = sec.Key("DB_TYPE").String()
 | 
				
			||||||
	if DbCfg.Type == "sqlite3" {
 | 
						switch DbCfg.Type {
 | 
				
			||||||
		UseSQLite3 = true
 | 
						case "sqlite3":
 | 
				
			||||||
 | 
							setting.UseSQLite3 = true
 | 
				
			||||||
 | 
						case "mysql":
 | 
				
			||||||
 | 
							setting.UseMySQL = true
 | 
				
			||||||
 | 
						case "postgres":
 | 
				
			||||||
 | 
							setting.UsePostgreSQL = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	DbCfg.Host = sec.Key("HOST").String()
 | 
						DbCfg.Host = sec.Key("HOST").String()
 | 
				
			||||||
	DbCfg.Name = sec.Key("NAME").String()
 | 
						DbCfg.Name = sec.Key("NAME").String()
 | 
				
			||||||
@@ -103,6 +120,7 @@ func NewTestEngine(x *xorm.Engine) (err error) {
 | 
				
			|||||||
		return fmt.Errorf("connect to database: %v", err)
 | 
							return fmt.Errorf("connect to database: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x.SetMapper(core.GonicMapper{})
 | 
				
			||||||
	return x.Sync(tables...)
 | 
						return x.Sync(tables...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,6 +130,8 @@ func SetEngine() (err error) {
 | 
				
			|||||||
		return fmt.Errorf("connect to database: %v", err)
 | 
							return fmt.Errorf("connect to database: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x.SetMapper(core.GonicMapper{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// WARNING: for serv command, MUST remove the output to os.stdout,
 | 
						// WARNING: for serv command, MUST remove the output to os.stdout,
 | 
				
			||||||
	// so use log file to instead print to stdout.
 | 
						// so use log file to instead print to stdout.
 | 
				
			||||||
	logPath := path.Join(setting.LogRootPath, "xorm.log")
 | 
						logPath := path.Join(setting.LogRootPath, "xorm.log")
 | 
				
			||||||
@@ -136,13 +156,14 @@ func NewEngine() (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// if err = migrations.Migrate(x); err != nil {
 | 
						if err = migrations.Migrate(x); err != nil {
 | 
				
			||||||
	// 	return err
 | 
							return fmt.Errorf("migrate: %v", err)
 | 
				
			||||||
	// }
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
 | 
						if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
 | 
				
			||||||
		return fmt.Errorf("sync database struct error: %v\n", err)
 | 
							return fmt.Errorf("sync database struct error: %v\n", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										641
									
								
								models/org.go
									
									
									
									
									
								
							
							
						
						
									
										641
									
								
								models/org.go
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										752
									
								
								models/repo.go
									
									
									
									
									
								
							
							
						
						
									
										752
									
								
								models/repo.go
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -231,7 +231,7 @@ func (u *User) GetOrganizations() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	u.Orgs = make([]*User, len(ous))
 | 
						u.Orgs = make([]*User, len(ous))
 | 
				
			||||||
	for i, ou := range ous {
 | 
						for i, ou := range ous {
 | 
				
			||||||
		u.Orgs[i], err = GetUserById(ou.OrgId)
 | 
							u.Orgs[i], err = GetUserById(ou.OrgID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -398,63 +398,7 @@ func ChangeUserName(u *User, newUserName string) (err error) {
 | 
				
			|||||||
		return ErrUserNameIllegal
 | 
							return ErrUserNameIllegal
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	newUserName = strings.ToLower(newUserName)
 | 
						return os.Rename(UserPath(u.LowerName), UserPath(newUserName))
 | 
				
			||||||
	if u.LowerName == newUserName {
 | 
					 | 
				
			||||||
		// User only change letter cases.
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Update accesses of user.
 | 
					 | 
				
			||||||
	accesses := make([]Access, 0, 10)
 | 
					 | 
				
			||||||
	if err = x.Find(&accesses, &Access{UserName: u.LowerName}); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sess := x.NewSession()
 | 
					 | 
				
			||||||
	defer sess.Close()
 | 
					 | 
				
			||||||
	if err = sess.Begin(); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := range accesses {
 | 
					 | 
				
			||||||
		accesses[i].UserName = newUserName
 | 
					 | 
				
			||||||
		if strings.HasPrefix(accesses[i].RepoName, u.LowerName+"/") {
 | 
					 | 
				
			||||||
			accesses[i].RepoName = strings.Replace(accesses[i].RepoName, u.LowerName, newUserName, 1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err = UpdateAccessWithSession(sess, &accesses[i]); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	repos, err := GetRepositories(u.Id, true)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i := range repos {
 | 
					 | 
				
			||||||
		accesses = make([]Access, 0, 10)
 | 
					 | 
				
			||||||
		// Update accesses of user repository.
 | 
					 | 
				
			||||||
		if err = x.Find(&accesses, &Access{RepoName: u.LowerName + "/" + repos[i].LowerName}); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for j := range accesses {
 | 
					 | 
				
			||||||
			// if the access is not the user's access (already updated above)
 | 
					 | 
				
			||||||
			if accesses[j].UserName != u.LowerName {
 | 
					 | 
				
			||||||
				accesses[j].RepoName = newUserName + "/" + repos[i].LowerName
 | 
					 | 
				
			||||||
				if err = UpdateAccessWithSession(sess, &accesses[j]); err != nil {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Change user directory name.
 | 
					 | 
				
			||||||
	if err = os.Rename(UserPath(u.LowerName), UserPath(newUserName)); err != nil {
 | 
					 | 
				
			||||||
		sess.Rollback()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sess.Commit()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateUser updates user's information.
 | 
					// UpdateUser updates user's information.
 | 
				
			||||||
@@ -527,7 +471,7 @@ func DeleteUser(u *User) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Delete all accesses.
 | 
						// Delete all accesses.
 | 
				
			||||||
	if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
 | 
						if _, err = x.Delete(&Access{UserID: u.Id}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Delete all alternative email addresses
 | 
						// Delete all alternative email addresses
 | 
				
			||||||
@@ -570,8 +514,7 @@ func UserPath(userName string) string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func GetUserByKeyId(keyId int64) (*User, error) {
 | 
					func GetUserByKeyId(keyId int64) (*User, error) {
 | 
				
			||||||
	user := new(User)
 | 
						user := new(User)
 | 
				
			||||||
	rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?"
 | 
						has, err := x.Sql("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyId).Get(user)
 | 
				
			||||||
	has, err := x.Sql(rawSql, keyId).Get(user)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
@@ -580,10 +523,9 @@ func GetUserByKeyId(keyId int64) (*User, error) {
 | 
				
			|||||||
	return user, nil
 | 
						return user, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUserById returns the user object by given ID if exists.
 | 
					func getUserById(e Engine, id int64) (*User, error) {
 | 
				
			||||||
func GetUserById(id int64) (*User, error) {
 | 
					 | 
				
			||||||
	u := new(User)
 | 
						u := new(User)
 | 
				
			||||||
	has, err := x.Id(id).Get(u)
 | 
						has, err := e.Id(id).Get(u)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !has {
 | 
				
			||||||
@@ -592,6 +534,11 @@ func GetUserById(id int64) (*User, error) {
 | 
				
			|||||||
	return u, nil
 | 
						return u, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUserById returns the user object by given ID if exists.
 | 
				
			||||||
 | 
					func GetUserById(id int64) (*User, error) {
 | 
				
			||||||
 | 
						return getUserById(x, id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUserByName returns user by given name.
 | 
					// GetUserByName returns user by given name.
 | 
				
			||||||
func GetUserByName(name string) (*User, error) {
 | 
					func GetUserByName(name string) (*User, error) {
 | 
				
			||||||
	if len(name) == 0 {
 | 
						if len(name) == 0 {
 | 
				
			||||||
@@ -913,7 +860,7 @@ func UpdateMentions(userNames []string, issueId int64) error {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for _, orgUser := range orgUsers {
 | 
							for _, orgUser := range orgUsers {
 | 
				
			||||||
			tempIds = append(tempIds, orgUser.Id)
 | 
								tempIds = append(tempIds, orgUser.ID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ids = append(ids, tempIds...)
 | 
							ids = append(ids, tempIds...)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,15 +38,25 @@ type Context struct {
 | 
				
			|||||||
	IsSigned    bool
 | 
						IsSigned    bool
 | 
				
			||||||
	IsBasicAuth bool
 | 
						IsBasicAuth bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Repo struct {
 | 
						Repo RepoContext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Org struct {
 | 
				
			||||||
		IsOwner      bool
 | 
							IsOwner      bool
 | 
				
			||||||
		IsTrueOwner  bool
 | 
							IsMember     bool
 | 
				
			||||||
 | 
							IsAdminTeam  bool // In owner team or team that has admin permission level.
 | 
				
			||||||
 | 
							Organization *models.User
 | 
				
			||||||
 | 
							OrgLink      string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Team *models.Team
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RepoContext struct {
 | 
				
			||||||
 | 
						AccessMode   models.AccessMode
 | 
				
			||||||
	IsWatching   bool
 | 
						IsWatching   bool
 | 
				
			||||||
	IsBranch     bool
 | 
						IsBranch     bool
 | 
				
			||||||
	IsTag        bool
 | 
						IsTag        bool
 | 
				
			||||||
	IsCommit     bool
 | 
						IsCommit     bool
 | 
				
			||||||
		IsAdmin      bool // Current user is admin level.
 | 
					 | 
				
			||||||
		HasAccess    bool
 | 
					 | 
				
			||||||
	Repository   *models.Repository
 | 
						Repository   *models.Repository
 | 
				
			||||||
	Owner        *models.User
 | 
						Owner        *models.User
 | 
				
			||||||
	Commit       *git.Commit
 | 
						Commit       *git.Commit
 | 
				
			||||||
@@ -60,17 +70,16 @@ type Context struct {
 | 
				
			|||||||
	CloneLink    models.CloneLink
 | 
						CloneLink    models.CloneLink
 | 
				
			||||||
	CommitsCount int
 | 
						CommitsCount int
 | 
				
			||||||
	Mirror       *models.Mirror
 | 
						Mirror       *models.Mirror
 | 
				
			||||||
	}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Org struct {
 | 
					// Return if the current user has write access for this repository
 | 
				
			||||||
		IsOwner      bool
 | 
					func (r RepoContext) IsOwner() bool {
 | 
				
			||||||
		IsMember     bool
 | 
						return r.AccessMode >= models.ACCESS_MODE_WRITE
 | 
				
			||||||
		IsAdminTeam  bool // In owner team or team that has admin permission level.
 | 
					}
 | 
				
			||||||
		Organization *models.User
 | 
					 | 
				
			||||||
		OrgLink      string
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Team *models.Team
 | 
					// Return if the current user has read access for this repository
 | 
				
			||||||
	}
 | 
					func (r RepoContext) HasAccess() bool {
 | 
				
			||||||
 | 
						return r.AccessMode >= models.ACCESS_MODE_READ
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasError returns true if error occurs in form validation.
 | 
					// HasError returns true if error occurs in form validation.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ctx.Data["Team"] = ctx.Org.Team
 | 
								ctx.Data["Team"] = ctx.Org.Team
 | 
				
			||||||
			ctx.Org.IsAdminTeam = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.Authorize == models.ORG_ADMIN
 | 
								ctx.Org.IsAdminTeam = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.Authorize >= models.ACCESS_MODE_ADMIN
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Data["IsAdminTeam"] = ctx.Org.IsAdminTeam
 | 
							ctx.Data["IsAdminTeam"] = ctx.Org.IsAdminTeam
 | 
				
			||||||
		if requireAdminTeam && !ctx.Org.IsAdminTeam {
 | 
							if requireAdminTeam && !ctx.Org.IsAdminTeam {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@
 | 
				
			|||||||
package middleware
 | 
					package middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -29,17 +28,10 @@ func ApiRepoAssignment() macaron.Handler {
 | 
				
			|||||||
			err error
 | 
								err error
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Collaborators who have write access can be seen as owners.
 | 
							// Check if the user is the same as the repository owner.
 | 
				
			||||||
		if ctx.IsSigned {
 | 
							if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
 | 
				
			||||||
			ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE)
 | 
								u = ctx.User
 | 
				
			||||||
			if err != nil {
 | 
							} else {
 | 
				
			||||||
				ctx.JSON(500, &base.ApiJsonErr{"HasAccess: " + err.Error(), base.DOC_URL})
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			ctx.Repo.IsTrueOwner = ctx.User.LowerName == strings.ToLower(userName)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if !ctx.Repo.IsTrueOwner {
 | 
					 | 
				
			||||||
			u, err = models.GetUserByName(userName)
 | 
								u, err = models.GetUserByName(userName)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				if err == models.ErrUserNotExist {
 | 
									if err == models.ErrUserNotExist {
 | 
				
			||||||
@@ -49,67 +41,37 @@ func ApiRepoAssignment() macaron.Handler {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			u = ctx.User
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Repo.Owner = u
 | 
							ctx.Repo.Owner = u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Organization owner team members are true owners as well.
 | 
					 | 
				
			||||||
		if ctx.IsSigned && ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOwnedBy(ctx.User.Id) {
 | 
					 | 
				
			||||||
			ctx.Repo.IsTrueOwner = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Get repository.
 | 
							// Get repository.
 | 
				
			||||||
		repo, err := models.GetRepositoryByName(u.Id, repoName)
 | 
							repo, err := models.GetRepositoryByName(u.Id, repoName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err == models.ErrRepoNotExist {
 | 
								if err == models.ErrRepoNotExist {
 | 
				
			||||||
				ctx.Error(404)
 | 
									ctx.Error(404)
 | 
				
			||||||
				return
 | 
								} else {
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
				ctx.JSON(500, &base.ApiJsonErr{"GetRepositoryByName: " + err.Error(), base.DOC_URL})
 | 
									ctx.JSON(500, &base.ApiJsonErr{"GetRepositoryByName: " + err.Error(), base.DOC_URL})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		} else if err = repo.GetOwner(); err != nil {
 | 
							} else if err = repo.GetOwner(); err != nil {
 | 
				
			||||||
			ctx.JSON(500, &base.ApiJsonErr{"GetOwner: " + err.Error(), base.DOC_URL})
 | 
								ctx.JSON(500, &base.ApiJsonErr{"GetOwner: " + err.Error(), base.DOC_URL})
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check if the mirror repository owner(mirror repository doesn't have access).
 | 
							mode, err := models.AccessLevel(ctx.User, repo)
 | 
				
			||||||
		if ctx.IsSigned && !ctx.Repo.IsOwner {
 | 
					 | 
				
			||||||
			if repo.OwnerId == ctx.User.Id {
 | 
					 | 
				
			||||||
				ctx.Repo.IsOwner = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Check if current user has admin permission to repository.
 | 
					 | 
				
			||||||
			if u.IsOrganization() {
 | 
					 | 
				
			||||||
				auth, err := models.GetHighestAuthorize(u.Id, ctx.User.Id, repo.Id, 0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
					ctx.JSON(500, &base.ApiJsonErr{"GetHighestAuthorize: " + err.Error(), base.DOC_URL})
 | 
								ctx.JSON(500, &base.ApiJsonErr{"AccessLevel: " + err.Error(), base.DOC_URL})
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
				if auth == models.ORG_ADMIN {
 | 
					
 | 
				
			||||||
					ctx.Repo.IsOwner = true
 | 
							ctx.Repo.AccessMode = mode
 | 
				
			||||||
					ctx.Repo.IsAdmin = true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check access.
 | 
							// Check access.
 | 
				
			||||||
		if repo.IsPrivate && !ctx.Repo.IsOwner {
 | 
							if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
 | 
				
			||||||
			if ctx.User == nil {
 | 
					 | 
				
			||||||
			ctx.Error(404)
 | 
								ctx.Error(404)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				ctx.JSON(500, &base.ApiJsonErr{"HasAccess: " + err.Error(), base.DOC_URL})
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			} else if !hasAccess {
 | 
					 | 
				
			||||||
				ctx.Error(404)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ctx.Repo.HasAccess = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ctx.Repo.Repository = repo
 | 
							ctx.Repo.Repository = repo
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -242,101 +204,49 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
 | 
				
			|||||||
			refName = ctx.Params(":path")
 | 
								refName = ctx.Params(":path")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Collaborators who have write access can be seen as owners.
 | 
							// Check if the user is the same as the repository owner
 | 
				
			||||||
		if ctx.IsSigned {
 | 
							if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
 | 
				
			||||||
			ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE)
 | 
								u = ctx.User
 | 
				
			||||||
			if err != nil {
 | 
							} else {
 | 
				
			||||||
				ctx.Handle(500, "HasAccess", err)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			ctx.Repo.IsTrueOwner = ctx.User.LowerName == strings.ToLower(userName)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if !ctx.Repo.IsTrueOwner {
 | 
					 | 
				
			||||||
			u, err = models.GetUserByName(userName)
 | 
								u, err = models.GetUserByName(userName)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				if err == models.ErrUserNotExist {
 | 
									if err == models.ErrUserNotExist {
 | 
				
			||||||
					ctx.Handle(404, "GetUserByName", err)
 | 
										ctx.Handle(404, "GetUserByName", err)
 | 
				
			||||||
				} else if redirect {
 | 
					 | 
				
			||||||
					log.Error(4, "GetUserByName", err)
 | 
					 | 
				
			||||||
					ctx.Redirect(setting.AppSubUrl + "/")
 | 
					 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					ctx.Handle(500, "GetUserByName", err)
 | 
										ctx.Handle(500, "GetUserByName", err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			u = ctx.User
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if u == nil {
 | 
					 | 
				
			||||||
			if redirect {
 | 
					 | 
				
			||||||
				ctx.Redirect(setting.AppSubUrl + "/")
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			ctx.Handle(404, "RepoAssignment", errors.New("invliad user account for single repository"))
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Repo.Owner = u
 | 
							ctx.Repo.Owner = u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Organization owner team members are true owners as well.
 | 
					 | 
				
			||||||
		if ctx.IsSigned && ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOwnedBy(ctx.User.Id) {
 | 
					 | 
				
			||||||
			ctx.Repo.IsTrueOwner = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Get repository.
 | 
							// Get repository.
 | 
				
			||||||
		repo, err := models.GetRepositoryByName(u.Id, repoName)
 | 
							repo, err := models.GetRepositoryByName(u.Id, repoName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err == models.ErrRepoNotExist {
 | 
								if err == models.ErrRepoNotExist {
 | 
				
			||||||
				ctx.Handle(404, "GetRepositoryByName", err)
 | 
									ctx.Handle(404, "GetRepositoryByName", err)
 | 
				
			||||||
				return
 | 
								} else {
 | 
				
			||||||
			} else if redirect {
 | 
					 | 
				
			||||||
				ctx.Redirect(setting.AppSubUrl + "/")
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
				ctx.Handle(500, "GetRepositoryByName", err)
 | 
									ctx.Handle(500, "GetRepositoryByName", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		} else if err = repo.GetOwner(); err != nil {
 | 
							} else if err = repo.GetOwner(); err != nil {
 | 
				
			||||||
			ctx.Handle(500, "GetOwner", err)
 | 
								ctx.Handle(500, "GetOwner", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check if the mirror repository owner(mirror repository doesn't have access).
 | 
							mode, err := models.AccessLevel(ctx.User, repo)
 | 
				
			||||||
		if ctx.IsSigned && !ctx.Repo.IsOwner {
 | 
					 | 
				
			||||||
			if repo.OwnerId == ctx.User.Id {
 | 
					 | 
				
			||||||
				ctx.Repo.IsOwner = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Check if current user has admin permission to repository.
 | 
					 | 
				
			||||||
			if u.IsOrganization() {
 | 
					 | 
				
			||||||
				auth, err := models.GetHighestAuthorize(u.Id, ctx.User.Id, repo.Id, 0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
					ctx.Handle(500, "GetHighestAuthorize", err)
 | 
								ctx.Handle(500, "AccessLevel", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
				if auth == models.ORG_ADMIN {
 | 
							ctx.Repo.AccessMode = mode
 | 
				
			||||||
					ctx.Repo.IsOwner = true
 | 
					 | 
				
			||||||
					ctx.Repo.IsAdmin = true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check access.
 | 
							// Check access.
 | 
				
			||||||
		if repo.IsPrivate && !ctx.Repo.IsOwner {
 | 
							if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
 | 
				
			||||||
			if ctx.User == nil {
 | 
								ctx.Handle(404, "no access right", err)
 | 
				
			||||||
				ctx.Handle(404, "HasAccess", nil)
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				ctx.Handle(500, "HasAccess", err)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			} else if !hasAccess {
 | 
					 | 
				
			||||||
				ctx.Handle(404, "HasAccess", nil)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ctx.Repo.HasAccess = true
 | 
					 | 
				
			||||||
		ctx.Data["HasAccess"] = true
 | 
							ctx.Data["HasAccess"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if repo.IsMirror {
 | 
							if repo.IsMirror {
 | 
				
			||||||
@@ -383,8 +293,8 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
 | 
				
			|||||||
		ctx.Data["Title"] = u.Name + "/" + repo.Name
 | 
							ctx.Data["Title"] = u.Name + "/" + repo.Name
 | 
				
			||||||
		ctx.Data["Repository"] = repo
 | 
							ctx.Data["Repository"] = repo
 | 
				
			||||||
		ctx.Data["Owner"] = ctx.Repo.Repository.Owner
 | 
							ctx.Data["Owner"] = ctx.Repo.Repository.Owner
 | 
				
			||||||
		ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
 | 
							ctx.Data["IsRepositoryOwner"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_WRITE
 | 
				
			||||||
		ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
 | 
							ctx.Data["IsRepositoryAdmin"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_ADMIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Data["DisableSSH"] = setting.DisableSSH
 | 
							ctx.Data["DisableSSH"] = setting.DisableSSH
 | 
				
			||||||
		ctx.Repo.CloneLink, err = repo.CloneLink()
 | 
							ctx.Repo.CloneLink, err = repo.CloneLink()
 | 
				
			||||||
@@ -438,9 +348,9 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func RequireTrueOwner() macaron.Handler {
 | 
					func RequireAdmin() macaron.Handler {
 | 
				
			||||||
	return func(ctx *Context) {
 | 
						return func(ctx *Context) {
 | 
				
			||||||
		if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin {
 | 
							if ctx.Repo.AccessMode < models.ACCESS_MODE_ADMIN {
 | 
				
			||||||
			if !ctx.IsSigned {
 | 
								if !ctx.IsSigned {
 | 
				
			||||||
				ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
 | 
									ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
 | 
				
			||||||
				ctx.Redirect(setting.AppSubUrl + "/user/login")
 | 
									ctx.Redirect(setting.AppSubUrl + "/user/login")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,6 +67,11 @@ var (
 | 
				
			|||||||
	CookieRememberName   string
 | 
						CookieRememberName   string
 | 
				
			||||||
	ReverseProxyAuthUser string
 | 
						ReverseProxyAuthUser string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Database settings.
 | 
				
			||||||
 | 
						UseSQLite3    bool
 | 
				
			||||||
 | 
						UseMySQL      bool
 | 
				
			||||||
 | 
						UsePostgreSQL bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Webhook settings.
 | 
						// Webhook settings.
 | 
				
			||||||
	Webhook struct {
 | 
						Webhook struct {
 | 
				
			||||||
		TaskInterval   int
 | 
							TaskInterval   int
 | 
				
			||||||
@@ -267,10 +272,6 @@ func NewConfigContext() {
 | 
				
			|||||||
		"StampNano":   time.StampNano,
 | 
							"StampNano":   time.StampNano,
 | 
				
			||||||
	}[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")]
 | 
						}[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = os.MkdirAll(AttachmentPath, os.ModePerm); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(4, "Could not create directory %s: %s", AttachmentPath, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	RunUser = Cfg.Section("").Key("RUN_USER").String()
 | 
						RunUser = Cfg.Section("").Key("RUN_USER").String()
 | 
				
			||||||
	curUser := os.Getenv("USER")
 | 
						curUser := os.Getenv("USER")
 | 
				
			||||||
	if len(curUser) == 0 {
 | 
						if len(curUser) == 0 {
 | 
				
			||||||
@@ -293,9 +294,6 @@ func NewConfigContext() {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		RepoRootPath = filepath.Clean(RepoRootPath)
 | 
							RepoRootPath = filepath.Clean(RepoRootPath)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(4, "Fail to create repository root path(%s): %v", RepoRootPath, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
 | 
						ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sec = Cfg.Section("picture")
 | 
						sec = Cfg.Section("picture")
 | 
				
			||||||
@@ -304,7 +302,6 @@ func NewConfigContext() {
 | 
				
			|||||||
	if !filepath.IsAbs(AvatarUploadPath) {
 | 
						if !filepath.IsAbs(AvatarUploadPath) {
 | 
				
			||||||
		AvatarUploadPath = path.Join(workDir, AvatarUploadPath)
 | 
							AvatarUploadPath = path.Join(workDir, AvatarUploadPath)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	os.MkdirAll(AvatarUploadPath, os.ModePerm)
 | 
					 | 
				
			||||||
	switch sec.Key("GRAVATAR_SOURCE").MustString("gravatar") {
 | 
						switch sec.Key("GRAVATAR_SOURCE").MustString("gravatar") {
 | 
				
			||||||
	case "duoshuo":
 | 
						case "duoshuo":
 | 
				
			||||||
		GravatarSource = "http://gravatar.duoshuo.com/avatar/"
 | 
							GravatarSource = "http://gravatar.duoshuo.com/avatar/"
 | 
				
			||||||
@@ -369,9 +366,11 @@ func newLogService() {
 | 
				
			|||||||
			log.Fatal(4, "Unknown log mode: %s", mode)
 | 
								log.Fatal(4, "Unknown log mode: %s", mode)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
 | 
				
			||||||
		// Log level.
 | 
							// Log level.
 | 
				
			||||||
		levelName := Cfg.Section("log."+mode).Key("LEVEL").In("Trace",
 | 
							levelName := Cfg.Section("log."+mode).Key("LEVEL").In(
 | 
				
			||||||
			[]string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"})
 | 
								Cfg.Section("log").Key("LEVEL").In("Trace", validLevels),
 | 
				
			||||||
 | 
								validLevels)
 | 
				
			||||||
		level, ok := logLevels[levelName]
 | 
							level, ok := logLevels[levelName]
 | 
				
			||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			log.Fatal(4, "Unknown log level: %s", levelName)
 | 
								log.Fatal(4, "Unknown log level: %s", levelName)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -238,28 +238,31 @@ func ListMyRepos(ctx *middleware.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	numOwnRepos := len(ownRepos)
 | 
						numOwnRepos := len(ownRepos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	collaRepos, err := models.GetCollaborativeRepos(ctx.User.Name)
 | 
						accessibleRepos, err := ctx.User.GetAccessibleRepositories()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.JSON(500, &base.ApiJsonErr{"GetCollaborativeRepos: " + err.Error(), base.DOC_URL})
 | 
							ctx.JSON(500, &base.ApiJsonErr{"GetAccessibleRepositories: " + err.Error(), base.DOC_URL})
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repos := make([]*api.Repository, numOwnRepos+len(collaRepos))
 | 
						repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
 | 
				
			||||||
	for i := range ownRepos {
 | 
						for i := range ownRepos {
 | 
				
			||||||
		repos[i] = ToApiRepository(ctx.User, ownRepos[i], api.Permission{true, true, true})
 | 
							repos[i] = ToApiRepository(ctx.User, ownRepos[i], api.Permission{true, true, true})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i := range collaRepos {
 | 
						i := numOwnRepos
 | 
				
			||||||
		if err = collaRepos[i].GetOwner(); err != nil {
 | 
					
 | 
				
			||||||
 | 
						for repo, access := range accessibleRepos {
 | 
				
			||||||
 | 
							if err = repo.GetOwner(); err != nil {
 | 
				
			||||||
			ctx.JSON(500, &base.ApiJsonErr{"GetOwner: " + err.Error(), base.DOC_URL})
 | 
								ctx.JSON(500, &base.ApiJsonErr{"GetOwner: " + err.Error(), base.DOC_URL})
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		j := i + numOwnRepos
 | 
					
 | 
				
			||||||
		repos[j] = ToApiRepository(collaRepos[i].Owner, collaRepos[i].Repository, api.Permission{false, collaRepos[i].CanPush, true})
 | 
							repos[i] = ToApiRepository(repo.Owner, repo, api.Permission{false, access >= models.ACCESS_MODE_WRITE, true})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// FIXME: cache result to reduce DB query?
 | 
							// FIXME: cache result to reduce DB query?
 | 
				
			||||||
		if collaRepos[i].Owner.IsOrganization() && collaRepos[i].Owner.IsOwnedBy(ctx.User.Id) {
 | 
							if repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(ctx.User.Id) {
 | 
				
			||||||
			repos[j].Permissions.Admin = true
 | 
								repos[i].Permissions.Admin = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							i++
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(200, &repos)
 | 
						ctx.JSON(200, &repos)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetRepoRawFile(ctx *middleware.Context) {
 | 
					func GetRepoRawFile(ctx *middleware.Context) {
 | 
				
			||||||
	if ctx.Repo.Repository.IsPrivate && !ctx.Repo.HasAccess {
 | 
						if !ctx.Repo.HasAccess() {
 | 
				
			||||||
		ctx.Error(404)
 | 
							ctx.Error(404)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -224,6 +224,7 @@ func InstallPost(ctx *middleware.Context, form auth.InstallForm) {
 | 
				
			|||||||
	cfg.Section("session").Key("PROVIDER").SetValue("file")
 | 
						cfg.Section("session").Key("PROVIDER").SetValue("file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cfg.Section("log").Key("MODE").SetValue("file")
 | 
						cfg.Section("log").Key("MODE").SetValue("file")
 | 
				
			||||||
 | 
						cfg.Section("log").Key("LEVEL").SetValue("Info")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
 | 
						cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
 | 
				
			||||||
	cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15))
 | 
						cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -165,14 +165,14 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Validate permission level.
 | 
						// Validate permission level.
 | 
				
			||||||
	var auth models.AuthorizeType
 | 
						var auth models.AccessMode
 | 
				
			||||||
	switch form.Permission {
 | 
						switch form.Permission {
 | 
				
			||||||
	case "read":
 | 
						case "read":
 | 
				
			||||||
		auth = models.ORG_READABLE
 | 
							auth = models.ACCESS_MODE_READ
 | 
				
			||||||
	case "write":
 | 
						case "write":
 | 
				
			||||||
		auth = models.ORG_WRITABLE
 | 
							auth = models.ACCESS_MODE_WRITE
 | 
				
			||||||
	case "admin":
 | 
						case "admin":
 | 
				
			||||||
		auth = models.ORG_ADMIN
 | 
							auth = models.ACCESS_MODE_ADMIN
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ctx.Error(401)
 | 
							ctx.Error(401)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -181,7 +181,7 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
 | 
				
			|||||||
	org := ctx.Org.Organization
 | 
						org := ctx.Org.Organization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t := &models.Team{
 | 
						t := &models.Team{
 | 
				
			||||||
		OrgId:       org.Id,
 | 
							OrgID:       org.Id,
 | 
				
			||||||
		Name:        form.TeamName,
 | 
							Name:        form.TeamName,
 | 
				
			||||||
		Description: form.Description,
 | 
							Description: form.Description,
 | 
				
			||||||
		Authorize:   auth,
 | 
							Authorize:   auth,
 | 
				
			||||||
@@ -246,14 +246,14 @@ func EditTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
 | 
				
			|||||||
	isAuthChanged := false
 | 
						isAuthChanged := false
 | 
				
			||||||
	if !t.IsOwnerTeam() {
 | 
						if !t.IsOwnerTeam() {
 | 
				
			||||||
		// Validate permission level.
 | 
							// Validate permission level.
 | 
				
			||||||
		var auth models.AuthorizeType
 | 
							var auth models.AccessMode
 | 
				
			||||||
		switch form.Permission {
 | 
							switch form.Permission {
 | 
				
			||||||
		case "read":
 | 
							case "read":
 | 
				
			||||||
			auth = models.ORG_READABLE
 | 
								auth = models.ACCESS_MODE_READ
 | 
				
			||||||
		case "write":
 | 
							case "write":
 | 
				
			||||||
			auth = models.ORG_WRITABLE
 | 
								auth = models.ACCESS_MODE_WRITE
 | 
				
			||||||
		case "admin":
 | 
							case "admin":
 | 
				
			||||||
			auth = models.ORG_ADMIN
 | 
								auth = models.ACCESS_MODE_ADMIN
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			ctx.Error(401)
 | 
								ctx.Error(401)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -131,18 +131,18 @@ func Http(ctx *middleware.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !isPublicPull {
 | 
							if !isPublicPull {
 | 
				
			||||||
			var tp = models.WRITABLE
 | 
								var tp = models.ACCESS_MODE_WRITE
 | 
				
			||||||
			if isPull {
 | 
								if isPull {
 | 
				
			||||||
				tp = models.READABLE
 | 
									tp = models.ACCESS_MODE_READ
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			has, err := models.HasAccess(authUsername, username+"/"+reponame, tp)
 | 
								has, err := models.HasAccess(authUser, repo, tp)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				ctx.Handle(401, "no basic auth and digit auth", nil)
 | 
									ctx.Handle(401, "no basic auth and digit auth", nil)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			} else if !has {
 | 
								} else if !has {
 | 
				
			||||||
				if tp == models.READABLE {
 | 
									if tp == models.ACCESS_MODE_READ {
 | 
				
			||||||
					has, err = models.HasAccess(authUsername, username+"/"+reponame, models.WRITABLE)
 | 
										has, err = models.HasAccess(authUser, repo, models.ACCESS_MODE_WRITE)
 | 
				
			||||||
					if err != nil || !has {
 | 
										if err != nil || !has {
 | 
				
			||||||
						ctx.Handle(401, "no basic auth and digit auth", nil)
 | 
											ctx.Handle(401, "no basic auth and digit auth", nil)
 | 
				
			||||||
						return
 | 
											return
 | 
				
			||||||
@@ -152,6 +152,11 @@ func Http(ctx *middleware.Context) {
 | 
				
			|||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if !isPull && repo.IsMirror {
 | 
				
			||||||
 | 
									ctx.Handle(401, "can't push to mirror", nil)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,7 +174,7 @@ func CreateIssue(ctx *middleware.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	us, err := models.GetCollaborators(strings.TrimPrefix(ctx.Repo.RepoLink, "/"))
 | 
						us, err := ctx.Repo.Repository.GetCollaborators()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
 | 
							ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -218,7 +218,7 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = models.GetCollaborators(strings.TrimPrefix(ctx.Repo.RepoLink, "/"))
 | 
						_, err = ctx.Repo.Repository.GetCollaborators()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		send(500, nil, err)
 | 
							send(500, nil, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -230,7 +230,7 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Only collaborators can assign.
 | 
						// Only collaborators can assign.
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		form.AssigneeId = 0
 | 
							form.AssigneeId = 0
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	issue := &models.Issue{
 | 
						issue := &models.Issue{
 | 
				
			||||||
@@ -246,8 +246,8 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
 | 
				
			|||||||
	if err := models.NewIssue(issue); err != nil {
 | 
						if err := models.NewIssue(issue); err != nil {
 | 
				
			||||||
		send(500, nil, err)
 | 
							send(500, nil, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	} else if err := models.NewIssueUserPairs(issue.RepoId, issue.Id, ctx.Repo.Owner.Id,
 | 
						} else if err := models.NewIssueUserPairs(ctx.Repo.Repository, issue.Id, ctx.Repo.Owner.Id,
 | 
				
			||||||
		ctx.User.Id, form.AssigneeId, ctx.Repo.Repository.Name); err != nil {
 | 
							ctx.User.Id, form.AssigneeId); err != nil {
 | 
				
			||||||
		send(500, nil, err)
 | 
							send(500, nil, err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -384,7 +384,7 @@ func ViewIssue(ctx *middleware.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get all collaborators.
 | 
						// Get all collaborators.
 | 
				
			||||||
	ctx.Data["Collaborators"], err = models.GetCollaborators(strings.TrimPrefix(ctx.Repo.RepoLink, "/"))
 | 
						ctx.Data["Collaborators"], err = ctx.Repo.Repository.GetCollaborators()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
 | 
							ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -434,7 +434,7 @@ func ViewIssue(ctx *middleware.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = issue.Name
 | 
						ctx.Data["Title"] = issue.Name
 | 
				
			||||||
	ctx.Data["Issue"] = issue
 | 
						ctx.Data["Issue"] = issue
 | 
				
			||||||
	ctx.Data["Comments"] = comments
 | 
						ctx.Data["Comments"] = comments
 | 
				
			||||||
	ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
 | 
						ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner() || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
 | 
				
			||||||
	ctx.Data["IsRepoToolbarIssues"] = true
 | 
						ctx.Data["IsRepoToolbarIssues"] = true
 | 
				
			||||||
	ctx.Data["IsRepoToolbarIssuesList"] = false
 | 
						ctx.Data["IsRepoToolbarIssuesList"] = false
 | 
				
			||||||
	ctx.HTML(200, ISSUE_VIEW)
 | 
						ctx.HTML(200, ISSUE_VIEW)
 | 
				
			||||||
@@ -457,7 +457,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner {
 | 
						if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Error(403)
 | 
							ctx.Error(403)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -484,7 +484,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UpdateIssueLabel(ctx *middleware.Context) {
 | 
					func UpdateIssueLabel(ctx *middleware.Context) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Error(403)
 | 
							ctx.Error(403)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -561,7 +561,7 @@ func UpdateIssueLabel(ctx *middleware.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UpdateIssueMilestone(ctx *middleware.Context) {
 | 
					func UpdateIssueMilestone(ctx *middleware.Context) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Error(403)
 | 
							ctx.Error(403)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -607,7 +607,7 @@ func UpdateIssueMilestone(ctx *middleware.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UpdateAssignee(ctx *middleware.Context) {
 | 
					func UpdateAssignee(ctx *middleware.Context) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Error(403)
 | 
							ctx.Error(403)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -753,7 +753,7 @@ func Comment(ctx *middleware.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Check if issue owner changes the status of issue.
 | 
						// Check if issue owner changes the status of issue.
 | 
				
			||||||
	var newStatus string
 | 
						var newStatus string
 | 
				
			||||||
	if ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id {
 | 
						if ctx.Repo.IsOwner() || issue.PosterId == ctx.User.Id {
 | 
				
			||||||
		newStatus = ctx.Query("change_status")
 | 
							newStatus = ctx.Query("change_status")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(newStatus) > 0 {
 | 
						if len(newStatus) > 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
	tags := make([]*models.Release, len(rawTags))
 | 
						tags := make([]*models.Release, len(rawTags))
 | 
				
			||||||
	for i, rawTag := range rawTags {
 | 
						for i, rawTag := range rawTags {
 | 
				
			||||||
		for j, rel := range rels {
 | 
							for j, rel := range rels {
 | 
				
			||||||
			if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner) {
 | 
								if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner()) {
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if rel.TagName == rawTag {
 | 
								if rel.TagName == rawTag {
 | 
				
			||||||
@@ -140,7 +140,7 @@ func Releases(ctx *middleware.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewRelease(ctx *middleware.Context) {
 | 
					func NewRelease(ctx *middleware.Context) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Handle(403, "release.ReleasesNew", nil)
 | 
							ctx.Handle(403, "release.ReleasesNew", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -153,7 +153,7 @@ func NewRelease(ctx *middleware.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
 | 
					func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Handle(403, "release.ReleasesNew", nil)
 | 
							ctx.Handle(403, "release.ReleasesNew", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -211,7 +211,7 @@ func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func EditRelease(ctx *middleware.Context) {
 | 
					func EditRelease(ctx *middleware.Context) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Handle(403, "release.ReleasesEdit", nil)
 | 
							ctx.Handle(403, "release.ReleasesEdit", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -234,7 +234,7 @@ func EditRelease(ctx *middleware.Context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func EditReleasePost(ctx *middleware.Context, form auth.EditReleaseForm) {
 | 
					func EditReleasePost(ctx *middleware.Context, form auth.EditReleaseForm) {
 | 
				
			||||||
	if !ctx.Repo.IsOwner {
 | 
						if !ctx.Repo.IsOwner() {
 | 
				
			||||||
		ctx.Handle(403, "release.EditReleasePost", nil)
 | 
							ctx.Handle(403, "release.EditReleasePost", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -349,7 +349,7 @@ func Action(ctx *middleware.Context) {
 | 
				
			|||||||
	case "unstar":
 | 
						case "unstar":
 | 
				
			||||||
		err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false)
 | 
							err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false)
 | 
				
			||||||
	case "desc":
 | 
						case "desc":
 | 
				
			||||||
		if !ctx.Repo.IsOwner {
 | 
							if !ctx.Repo.IsOwner() {
 | 
				
			||||||
			ctx.Error(404)
 | 
								ctx.Error(404)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@ import (
 | 
				
			|||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,15 +53,11 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
 | 
				
			|||||||
		newRepoName := form.RepoName
 | 
							newRepoName := form.RepoName
 | 
				
			||||||
		// Check if repository name has been changed.
 | 
							// Check if repository name has been changed.
 | 
				
			||||||
		if ctx.Repo.Repository.Name != newRepoName {
 | 
							if ctx.Repo.Repository.Name != newRepoName {
 | 
				
			||||||
			isExist, err := models.IsRepositoryExist(ctx.Repo.Owner, newRepoName)
 | 
								if models.IsRepositoryExist(ctx.Repo.Owner, newRepoName) {
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				ctx.Handle(500, "IsRepositoryExist", err)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			} else if isExist {
 | 
					 | 
				
			||||||
				ctx.Data["Err_RepoName"] = true
 | 
									ctx.Data["Err_RepoName"] = true
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, nil)
 | 
									ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, nil)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			} else if err = models.ChangeRepositoryName(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name, newRepoName); err != nil {
 | 
								} else if err := models.ChangeRepositoryName(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name, newRepoName); err != nil {
 | 
				
			||||||
				if err == models.ErrRepoNameIllegal {
 | 
									if err == models.ErrRepoNameIllegal {
 | 
				
			||||||
					ctx.Data["Err_RepoName"] = true
 | 
										ctx.Data["Err_RepoName"] = true
 | 
				
			||||||
					ctx.RenderWithErr(ctx.Tr("form.illegal_repo_name"), SETTINGS_OPTIONS, nil)
 | 
										ctx.RenderWithErr(ctx.Tr("form.illegal_repo_name"), SETTINGS_OPTIONS, nil)
 | 
				
			||||||
@@ -169,22 +164,12 @@ func SettingsCollaboration(ctx *middleware.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = ctx.Tr("repo.settings")
 | 
						ctx.Data["Title"] = ctx.Tr("repo.settings")
 | 
				
			||||||
	ctx.Data["PageIsSettingsCollaboration"] = true
 | 
						ctx.Data["PageIsSettingsCollaboration"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repoLink := path.Join(ctx.Repo.Owner.LowerName, ctx.Repo.Repository.LowerName)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ctx.Req.Method == "POST" {
 | 
						if ctx.Req.Method == "POST" {
 | 
				
			||||||
		name := strings.ToLower(ctx.Query("collaborator"))
 | 
							name := strings.ToLower(ctx.Query("collaborator"))
 | 
				
			||||||
		if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
 | 
							if len(name) == 0 || ctx.Repo.Owner.LowerName == name {
 | 
				
			||||||
			ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
 | 
								ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		has, err := models.HasAccess(name, repoLink, models.WRITABLE)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			ctx.Handle(500, "HasAccess", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		} else if has {
 | 
					 | 
				
			||||||
			ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		u, err := models.GetUserByName(name)
 | 
							u, err := models.GetUserByName(name)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -204,9 +189,8 @@ func SettingsCollaboration(ctx *middleware.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err = models.AddAccess(&models.Access{UserName: name, RepoName: repoLink,
 | 
							if err = ctx.Repo.Repository.AddCollaborator(u); err != nil {
 | 
				
			||||||
			Mode: models.WRITABLE}); err != nil {
 | 
								ctx.Handle(500, "AddCollaborator", err)
 | 
				
			||||||
			ctx.Handle(500, "AddAccess", err)
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -225,50 +209,27 @@ func SettingsCollaboration(ctx *middleware.Context) {
 | 
				
			|||||||
	// Delete collaborator.
 | 
						// Delete collaborator.
 | 
				
			||||||
	remove := strings.ToLower(ctx.Query("remove"))
 | 
						remove := strings.ToLower(ctx.Query("remove"))
 | 
				
			||||||
	if len(remove) > 0 && remove != ctx.Repo.Owner.LowerName {
 | 
						if len(remove) > 0 && remove != ctx.Repo.Owner.LowerName {
 | 
				
			||||||
		needDelete := true
 | 
							u, err := models.GetUserByName(remove)
 | 
				
			||||||
		if ctx.User.IsOrganization() {
 | 
					 | 
				
			||||||
			// Check if user belongs to a team that has access to this repository.
 | 
					 | 
				
			||||||
			auth, err := models.GetHighestAuthorize(ctx.Repo.Owner.Id, ctx.User.Id, ctx.Repo.Repository.Id, 0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
				ctx.Handle(500, "GetHighestAuthorize", err)
 | 
								ctx.Handle(500, "GetUserByName", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			if auth > 0 {
 | 
							if err := ctx.Repo.Repository.DeleteCollaborator(u); err != nil {
 | 
				
			||||||
				needDelete = false
 | 
								ctx.Handle(500, "DeleteCollaborator", err)
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if needDelete {
 | 
					 | 
				
			||||||
			if err := models.DeleteAccess(&models.Access{UserName: remove, RepoName: repoLink}); err != nil {
 | 
					 | 
				
			||||||
				ctx.Handle(500, "DeleteAccess", err)
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
 | 
							ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success"))
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	names, err := models.GetCollaboratorNames(repoLink)
 | 
						users, err := ctx.Repo.Repository.GetCollaborators()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.Handle(500, "GetCollaborators", err)
 | 
							ctx.Handle(500, "GetCollaborators", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	collaborators := make([]*models.User, 0, len(names))
 | 
						ctx.Data["Collaborators"] = users
 | 
				
			||||||
	for _, name := range names {
 | 
					 | 
				
			||||||
		u, err := models.GetUserByName(name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			ctx.Handle(500, "GetUserByName", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Does not show organization members.
 | 
					 | 
				
			||||||
		if ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOrgMember(u.Id) {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		collaborators = append(collaborators, u)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ctx.Data["Collaborators"] = collaborators
 | 
					 | 
				
			||||||
	ctx.HTML(200, COLLABORATION)
 | 
						ctx.HTML(200, COLLABORATION)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,13 +49,19 @@ func Dashboard(ctx *middleware.Context) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Normal user.
 | 
							// Normal user.
 | 
				
			||||||
		ctxUser = ctx.User
 | 
							ctxUser = ctx.User
 | 
				
			||||||
		collaborates, err := models.GetCollaborativeRepos(ctxUser.Name)
 | 
							collaborates, err := ctx.User.GetAccessibleRepositories()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Handle(500, "GetCollaborativeRepos", err)
 | 
								ctx.Handle(500, "GetAccessibleRepositories", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Data["CollaborateCount"] = len(collaborates)
 | 
					
 | 
				
			||||||
		ctx.Data["CollaborativeRepos"] = collaborates
 | 
							repositories := make([]*models.Repository, 0, len(collaborates))
 | 
				
			||||||
 | 
							for repo := range collaborates {
 | 
				
			||||||
 | 
								repositories = append(repositories, repo)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx.Data["CollaborateCount"] = len(repositories)
 | 
				
			||||||
 | 
							ctx.Data["CollaborativeRepos"] = repositories
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["ContextUser"] = ctxUser
 | 
						ctx.Data["ContextUser"] = ctxUser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -97,11 +103,15 @@ func Dashboard(ctx *middleware.Context) {
 | 
				
			|||||||
	feeds := make([]*models.Action, 0, len(actions))
 | 
						feeds := make([]*models.Action, 0, len(actions))
 | 
				
			||||||
	for _, act := range actions {
 | 
						for _, act := range actions {
 | 
				
			||||||
		if act.IsPrivate {
 | 
							if act.IsPrivate {
 | 
				
			||||||
			if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
 | 
								// This prevents having to retrieve the repository for each action
 | 
				
			||||||
				models.READABLE); !has {
 | 
								repo := &models.Repository{Id: act.RepoId, IsPrivate: true}
 | 
				
			||||||
 | 
								if act.RepoUserName != ctx.User.LowerName {
 | 
				
			||||||
 | 
									if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		// FIXME: cache results?
 | 
							// FIXME: cache results?
 | 
				
			||||||
		u, err := models.GetUserByName(act.ActUserName)
 | 
							u, err := models.GetUserByName(act.ActUserName)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -205,11 +215,15 @@ func Profile(ctx *middleware.Context) {
 | 
				
			|||||||
				if !ctx.IsSigned {
 | 
									if !ctx.IsSigned {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
 | 
									// This prevents having to retrieve the repository for each action
 | 
				
			||||||
					models.READABLE); !has {
 | 
									repo := &models.Repository{Id: act.RepoId, IsPrivate: true}
 | 
				
			||||||
 | 
									if act.RepoUserName != ctx.User.LowerName {
 | 
				
			||||||
 | 
										if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has {
 | 
				
			||||||
						continue
 | 
											continue
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			// FIXME: cache results?
 | 
								// FIXME: cache results?
 | 
				
			||||||
			u, err := models.GetUserByName(act.ActUserName)
 | 
								u, err := models.GetUserByName(act.ActUserName)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
0.5.14.0222 Beta
 | 
					0.5.16.0228 Beta
 | 
				
			||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<footer id="footer">
 | 
							<footer id="footer">
 | 
				
			||||||
		    <div class="container clear">
 | 
							    <div class="container clear">
 | 
				
			||||||
		        <p class="left" id="footer-rights">© 2015 GoGits · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> ·
 | 
							        <p class="left" id="footer-rights">© 2015 Gogs · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> ·
 | 
				
			||||||
		            {{.i18n.Tr "template"}}: <strong>{{call .TmplLoadTimes}}</strong></p>
 | 
							            {{.i18n.Tr "template"}}: <strong>{{call .TmplLoadTimes}}</strong></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		        <div class="right" id="footer-links">
 | 
							        <div class="right" id="footer-links">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div id="org-repo-list">
 | 
					    <div id="org-repo-list">
 | 
				
			||||||
		{{range .Repos}}
 | 
							{{range .Repos}}
 | 
				
			||||||
			{{if or (not .IsPrivate) (.HasAccess $.SignedUser.Name)}}
 | 
								{{if or (not .IsPrivate) (.HasAccess $.SignedUser)}}
 | 
				
			||||||
			<div class="org-repo-item">
 | 
								<div class="org-repo-item">
 | 
				
			||||||
        <ul class="org-repo-status right">
 | 
					        <ul class="org-repo-status right">
 | 
				
			||||||
          <li><i class="octicon octicon-star"></i> {{.NumStars}}</li>
 | 
					          <li><i class="octicon octicon-star"></i> {{.NumStars}}</li>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@
 | 
				
			|||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
            <li id="repo-header-fork">
 | 
					            <li id="repo-header-fork">
 | 
				
			||||||
                <a id="repo-header-fork-btn" {{if or (not $.IsRepositoryTrueOwner) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}>
 | 
					                <a id="repo-header-fork-btn" {{if or (not $.IsRepositoryAdmin) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}>
 | 
				
			||||||
                    <button class="btn btn-gray text-bold btn-radius">
 | 
					                    <button class="btn btn-gray text-bold btn-radius">
 | 
				
			||||||
                        <i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
 | 
					                        <i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
 | 
				
			||||||
                        <span class="num">{{.NumForks}}</span>
 | 
					                        <span class="num">{{.NumForks}}</span>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@
 | 
				
			|||||||
        <!-- <li>
 | 
					        <!-- <li>
 | 
				
			||||||
            <a class="radius" href="#"><i class="octicon octicon-organization"></i>contributors <span class="num right label label-gray label-radius">43</span></a>
 | 
					            <a class="radius" href="#"><i class="octicon octicon-organization"></i>contributors <span class="num right label label-gray label-radius">43</span></a>
 | 
				
			||||||
        </li> -->
 | 
					        </li> -->
 | 
				
			||||||
        {{if .IsRepositoryTrueOwner}}
 | 
					        {{if .IsRepositoryAdmin}}
 | 
				
			||||||
        <li class="border-bottom"></li>
 | 
					        <li class="border-bottom"></li>
 | 
				
			||||||
        <li>
 | 
					        <li>
 | 
				
			||||||
            <a class="radius" href="{{.RepoLink}}/settings"><i class="octicon octicon-tools"></i>{{.i18n.Tr "repo.settings"}}</a>
 | 
					            <a class="radius" href="{{.RepoLink}}/settings"><i class="octicon octicon-tools"></i>{{.i18n.Tr "repo.settings"}}</a>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@
 | 
				
			|||||||
                            <li><a href="#">Pulse</a></li>
 | 
					                            <li><a href="#">Pulse</a></li>
 | 
				
			||||||
                            <li><a href="#">Network</a></li>
 | 
					                            <li><a href="#">Network</a></li>
 | 
				
			||||||
                        </ul>
 | 
					                        </ul>
 | 
				
			||||||
                    </li> -->{{end}}{{if .IsRepositoryTrueOwner}}
 | 
					                    </li> -->{{end}}{{if .IsRepositoryAdmin}}
 | 
				
			||||||
                    <li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="{{.RepoLink}}/settings">Settings</a>
 | 
					                    <li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="{{.RepoLink}}/settings">Settings</a>
 | 
				
			||||||
                    </li>{{end}}
 | 
					                    </li>{{end}}
 | 
				
			||||||
                </ul>
 | 
					                </ul>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,7 +74,7 @@
 | 
				
			|||||||
                    <div class="tab-pane active">
 | 
					                    <div class="tab-pane active">
 | 
				
			||||||
                        <div id="org-repo-list">
 | 
					                        <div id="org-repo-list">
 | 
				
			||||||
                            {{range .Repos}}
 | 
					                            {{range .Repos}}
 | 
				
			||||||
                                {{if or (not .IsPrivate) (.HasAccess $.SignedUserName)}}
 | 
					                                {{if or (not .IsPrivate) (.HasAccess $.SignedUser)}}
 | 
				
			||||||
                                <div class="org-repo-item">
 | 
					                                <div class="org-repo-item">
 | 
				
			||||||
                                    <ul class="org-repo-status right">
 | 
					                                    <ul class="org-repo-status right">
 | 
				
			||||||
                                        <li><i class="octicon octicon-star"></i> {{.NumStars}}</li>
 | 
					                                        <li><i class="octicon octicon-star"></i> {{.NumStars}}</li>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user