add ssh supports(unfinished)
This commit is contained in:
		
							parent
							
								
									94311e187f
								
							
						
					
					
						commit
						be0ba9ea88
					
				
					 8 changed files with 305 additions and 39 deletions
				
			
		|  | @ -9,4 +9,4 @@ DB_TYPE = mysql | ||||||
| HOST =  | HOST =  | ||||||
| NAME = gogs | NAME = gogs | ||||||
| USER = root | USER = root | ||||||
| PASSWD = root | PASSWD =  | ||||||
|  |  | ||||||
							
								
								
									
										65
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								gogs.go
									
									
									
									
									
								
							|  | @ -1,44 +1,49 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2013-2014 gogs authors.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | //
 | ||||||
| // license that can be found in the LICENSE file.
 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
 | ||||||
|  | // not use this file except in compliance with the License. You may obtain
 | ||||||
|  | // a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | ||||||
|  | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | ||||||
|  | // License for the specific language governing permissions and limitations
 | ||||||
|  | // under the License.
 | ||||||
| 
 | 
 | ||||||
|  | // gogs(Go Git Service) is a Go clone of Github.
 | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"os" | ||||||
| 	"net/http" | 	"runtime" | ||||||
| 
 | 
 | ||||||
| 	"github.com/codegangsta/martini" | 	"github.com/codegangsta/cli" | ||||||
| 	"github.com/martini-contrib/render" |  | ||||||
| 
 |  | ||||||
| 	"github.com/gogits/gogs/routers" |  | ||||||
| 	"github.com/gogits/gogs/routers/user" |  | ||||||
| 	"github.com/gogits/gogs/utils" |  | ||||||
| 	"github.com/gogits/gogs/utils/log" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // +build go1.1
 | ||||||
|  | 
 | ||||||
|  | // Test that go1.1 tag above is included in builds. main.go refers to this definition.
 | ||||||
|  | const go11tag = true | ||||||
|  | 
 | ||||||
| const APP_VER = "0.0.0.0218" | const APP_VER = "0.0.0.0218" | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 
 | 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
| 	log.Info("%s %s", utils.Cfg.MustValue("", "APP_NAME"), APP_VER) | 	app := cli.NewApp() | ||||||
| 
 | 	app.Name = "gogs" | ||||||
| 	m := martini.Classic() | 	app.Usage = "Go Git Service" | ||||||
| 
 | 	app.Version = APP_VER | ||||||
| 	// Middleware.
 | 	app.Commands = []cli.Command{ | ||||||
| 	m.Use(render.Renderer()) | 		CmdWeb, | ||||||
| 
 | 		CmdServ, | ||||||
| 	// Routers.
 | 	} | ||||||
| 	m.Get("/", routers.Dashboard) | 	app.Flags = append(app.Flags, []cli.Flag{ | ||||||
| 	m.Get("/user/signin", user.SignIn) | 		cli.BoolFlag{"noterm", "disable color output"}, | ||||||
| 	m.Any("/user/signup", user.SignUp) | 	}...) | ||||||
| 
 | 	app.Run(os.Args) | ||||||
| 	listenAddr := fmt.Sprintf("%s:%s", |  | ||||||
| 		utils.Cfg.MustValue("server", "HTTP_ADDR"), |  | ||||||
| 		utils.Cfg.MustValue("server", "HTTP_PORT", "3000")) |  | ||||||
| 	log.Info("Listen: %s", listenAddr) |  | ||||||
| 	http.ListenAndServe(listenAddr, m) |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
| 	orm          *xorm.Engine | 	orm          *xorm.Engine | ||||||
| 	repoRootPath string | 	RepoRootPath string | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Members struct { | type Members struct { | ||||||
|  | @ -71,5 +71,9 @@ func setEngine() { | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	setEngine() | 	setEngine() | ||||||
| 	orm.Sync(new(User)) | 	err := orm.Sync(new(User), new(PublicKey), new(Repo), new(Access)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("sync database struct error: %s", err) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,15 +29,22 @@ type Repo struct { | ||||||
| // check if repository is exist
 | // check if repository is exist
 | ||||||
| func IsRepositoryExist(user *User, reposName string) (bool, error) { | func IsRepositoryExist(user *User, reposName string) (bool, error) { | ||||||
| 	repo := Repo{OwnerId: user.Id} | 	repo := Repo{OwnerId: user.Id} | ||||||
| 	// TODO: get repository by nocase name
 | 	has, err := orm.Where("lower_name = ?", strings.ToLower(reposName)).Get(&repo) | ||||||
| 	return orm.Where("lower_name = ?", strings.ToLower(reposName)).Get(&repo) | 	if err != nil { | ||||||
|  | 		return has, err | ||||||
|  | 	} | ||||||
|  | 	s, err := os.Stat(filepath.Join(RepoRootPath, user.Name, reposName)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	return s.IsDir(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //
 | //
 | ||||||
| // create a repository for a user or orgnaziation
 | // create a repository for a user or orgnaziation
 | ||||||
| //
 | //
 | ||||||
| func CreateRepository(user *User, reposName string) (*Repo, error) { | func CreateRepository(user *User, reposName string) (*Repo, error) { | ||||||
| 	p := filepath.Join(repoRootPath, user.Name) | 	p := filepath.Join(RepoRootPath, user.Name) | ||||||
| 	os.MkdirAll(p, os.ModePerm) | 	os.MkdirAll(p, os.ModePerm) | ||||||
| 	f := filepath.Join(p, reposName+".git") | 	f := filepath.Join(p, reposName+".git") | ||||||
| 	_, err := git.InitRepository(f, false) | 	_, err := git.InitRepository(f, false) | ||||||
|  | @ -108,7 +115,7 @@ func DeleteRepository(user *User, reposName string) (err error) { | ||||||
| 		session.Rollback() | 		session.Rollback() | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if err = os.RemoveAll(filepath.Join(repoRootPath, user.Name, reposName+".git")); err != nil { | 	if err = os.RemoveAll(filepath.Join(RepoRootPath, user.Name, reposName+".git")); err != nil { | ||||||
| 		// TODO: log and delete manully
 | 		// TODO: log and delete manully
 | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -123,6 +123,19 @@ func (user *User) EncodePasswd() error { | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func GetUserByKeyId(keyId int64) (*User, error) { | ||||||
|  | 	user := new(User) | ||||||
|  | 	has, err := orm.Sql("select a.* from user as a, public_key as b where a.id = b.owner_id and b.id=?", keyId).Get(user) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if !has { | ||||||
|  | 		err = errors.New("not exist key owner") | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	return user, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // LoginUserPlain validates user by raw user name and password.
 | // LoginUserPlain validates user by raw user name and password.
 | ||||||
| func LoginUserPlain(name, passwd string) (*User, error) { | func LoginUserPlain(name, passwd string) (*User, error) { | ||||||
| 	user := User{Name: name, Passwd: passwd} | 	user := User{Name: name, Passwd: passwd} | ||||||
|  |  | ||||||
							
								
								
									
										164
									
								
								serve.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								serve.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,164 @@ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"github.com/codegangsta/cli" | ||||||
|  | 	"github.com/gogits/gogs/models" | ||||||
|  | 	"github.com/gogits/gogs/utils/log" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	COMMANDS_READONLY = map[string]int{ | ||||||
|  | 		"git-upload-pack": models.AU_WRITABLE, | ||||||
|  | 		"git upload-pack": models.AU_WRITABLE, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	COMMANDS_WRITE = map[string]int{ | ||||||
|  | 		"git-receive-pack": models.AU_READABLE, | ||||||
|  | 		"git receive-pack": models.AU_READABLE, | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var CmdServ = cli.Command{ | ||||||
|  | 	Name:  "serv", | ||||||
|  | 	Usage: "just run", | ||||||
|  | 	Description: ` | ||||||
|  | gogs serv`, | ||||||
|  | 	Action: runServ, | ||||||
|  | 	Flags:  []cli.Flag{ | ||||||
|  | 	//cli.BoolFlag{"update, u", "update pakcage(s) and dependencies if any"},
 | ||||||
|  | 	//cli.BoolFlag{"verbose, v", "show process details"},
 | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func In(b string, sl map[string]int) bool { | ||||||
|  | 	_, e := sl[b] | ||||||
|  | 	return e | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func runServ(*cli.Context) { | ||||||
|  | 	keys := strings.Split(os.Args[2], "-") | ||||||
|  | 	if len(keys) != 2 { | ||||||
|  | 		fmt.Println("auth file format error") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	keyId, err := strconv.ParseInt(keys[1], 10, 64) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println("auth file format error") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	user, err := models.GetUserByKeyId(keyId) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println("You have no right to access") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cmd := os.Getenv("SSH_ORIGINAL_COMMAND") | ||||||
|  | 	if cmd == "" { | ||||||
|  | 		fmt.Printf("Hi %s! You've successfully authenticated, but Gogits does not provide shell access.\n", user.Name) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	f, _ := os.Create("test2.log") | ||||||
|  | 	f.WriteString(cmd) | ||||||
|  | 	f.Close() | ||||||
|  | 
 | ||||||
|  | 	log.Info("cmd is %s", cmd) | ||||||
|  | 
 | ||||||
|  | 	verb, args := parseCmd(cmd) | ||||||
|  | 	rr := strings.SplitN(strings.Trim(args, "'"), "/", 1) | ||||||
|  | 	if len(rr) != 2 { | ||||||
|  | 		fmt.Printf("Unavilable repository") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	repoName := rr[1] | ||||||
|  | 	if strings.HasSuffix(repoName, ".git") { | ||||||
|  | 		repoName = repoName[:len(repoName)-4] | ||||||
|  | 	} | ||||||
|  | 	isWrite := In(verb, COMMANDS_WRITE) | ||||||
|  | 	isRead := In(verb, COMMANDS_READONLY) | ||||||
|  | 	switch { | ||||||
|  | 	case isWrite: | ||||||
|  | 		has, err := models.HasAccess(user.Name, repoName, COMMANDS_WRITE[verb]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			fmt.Println("Inernel error") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if !has { | ||||||
|  | 			fmt.Println("You have no right to access this repository") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	case isRead: | ||||||
|  | 		has, err := models.HasAccess(user.Name, repoName, COMMANDS_READONLY[verb]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			fmt.Println("Inernel error") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if !has { | ||||||
|  | 			has, err = models.HasAccess(user.Name, repoName, COMMANDS_WRITE[verb]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				fmt.Println("Inernel error") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !has { | ||||||
|  | 			fmt.Println("You have no right to access this repository") | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		fmt.Println("Unknown command") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	isExist, err := models.IsRepositoryExist(user, repoName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Println("Inernel error") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !isExist { | ||||||
|  | 		if isRead { | ||||||
|  | 			fmt.Println("Repository is not exist") | ||||||
|  | 			return | ||||||
|  | 		} else if isWrite { | ||||||
|  | 			_, err := models.CreateRepository(user, repoName) | ||||||
|  | 			if err != nil { | ||||||
|  | 				fmt.Println("Create repository failed") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fullPath := filepath.Join(models.RepoRootPath, user.Name, repoName+".git") | ||||||
|  | 	newcmd := fmt.Sprintf("%s '%s'", verb, fullPath) | ||||||
|  | 	fmt.Println(newcmd) | ||||||
|  | 	gitcmd := exec.Command("git", "shell", "-c", newcmd) | ||||||
|  | 	gitcmd.Stdout = os.Stdout | ||||||
|  | 	gitcmd.Stderr = os.Stderr | ||||||
|  | 
 | ||||||
|  | 	err = gitcmd.Run() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("execute command error: %s", err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseCmd(cmd string) (string, string) { | ||||||
|  | 	ss := strings.SplitN(cmd, " ", 1) | ||||||
|  | 	if len(ss) != 2 { | ||||||
|  | 		return "", "" | ||||||
|  | 	} | ||||||
|  | 	verb, args := ss[0], ss[1] | ||||||
|  | 	if verb == "git" { | ||||||
|  | 		ss = strings.SplitN(args, " ", 1) | ||||||
|  | 		args = ss[1] | ||||||
|  | 		verb = fmt.Sprintf("%s %s", verb, ss[0]) | ||||||
|  | 	} | ||||||
|  | 	return verb, args | ||||||
|  | } | ||||||
|  | @ -7,17 +7,39 @@ package utils | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path" | ||||||
|  | 	"path/filepath" | ||||||
| 
 | 
 | ||||||
| 	"github.com/Unknwon/goconfig" | 	"github.com/Unknwon/goconfig" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var Cfg *goconfig.ConfigFile | var Cfg *goconfig.ConfigFile | ||||||
| 
 | 
 | ||||||
|  | func exeDir() (string, error) { | ||||||
|  | 	file, err := exec.LookPath(os.Args[0]) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	p, err := filepath.Abs(file) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return path.Dir(p), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func init() { | func init() { | ||||||
| 	var err error | 	var err error | ||||||
| 	Cfg, err = goconfig.LoadConfigFile("conf/app.ini") | 	workDir, err := exeDir() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Println("Cannot load config file 'app.ini'") | 		fmt.Printf("Fail to get work directory: %s\n", err) | ||||||
|  | 		os.Exit(2) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfgPath := filepath.Join(workDir, "conf", "app.ini") | ||||||
|  | 	Cfg, err = goconfig.LoadConfigFile(cfgPath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Printf("Cannot load config file '%s'\n", cfgPath) | ||||||
| 		os.Exit(2) | 		os.Exit(2) | ||||||
| 	} | 	} | ||||||
| 	Cfg.BlockMode = false | 	Cfg.BlockMode = false | ||||||
|  |  | ||||||
							
								
								
									
										51
									
								
								web.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								web.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | // Copyright 2014 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 main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"github.com/codegangsta/cli" | ||||||
|  | 	"github.com/codegangsta/martini" | ||||||
|  | 	"github.com/martini-contrib/render" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gogits/gogs/routers" | ||||||
|  | 	"github.com/gogits/gogs/routers/user" | ||||||
|  | 	"github.com/gogits/gogs/utils" | ||||||
|  | 	"github.com/gogits/gogs/utils/log" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var CmdWeb = cli.Command{ | ||||||
|  | 	Name:  "web", | ||||||
|  | 	Usage: "just run", | ||||||
|  | 	Description: ` | ||||||
|  | gogs web`, | ||||||
|  | 	Action: runWeb, | ||||||
|  | 	Flags:  []cli.Flag{ | ||||||
|  | 	//cli.BoolFlag{"update, u", "update pakcage(s) and dependencies if any"},
 | ||||||
|  | 	//cli.BoolFlag{"verbose, v", "show process details"},
 | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func runWeb(*cli.Context) { | ||||||
|  | 	log.Info("%s %s", utils.Cfg.MustValue("", "APP_NAME"), APP_VER) | ||||||
|  | 
 | ||||||
|  | 	m := martini.Classic() | ||||||
|  | 
 | ||||||
|  | 	// Middleware.
 | ||||||
|  | 	m.Use(render.Renderer()) | ||||||
|  | 
 | ||||||
|  | 	// Routers.
 | ||||||
|  | 	m.Get("/", routers.Dashboard) | ||||||
|  | 	m.Get("/user/signin", user.SignIn) | ||||||
|  | 	m.Any("/user/signup", user.SignUp) | ||||||
|  | 
 | ||||||
|  | 	listenAddr := fmt.Sprintf("%s:%s", | ||||||
|  | 		utils.Cfg.MustValue("server", "HTTP_ADDR"), | ||||||
|  | 		utils.Cfg.MustValue("server", "HTTP_PORT", "3000")) | ||||||
|  | 	log.Info("Listen: %s", listenAddr) | ||||||
|  | 	http.ListenAndServe(listenAddr, m) | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue