add ssh supports(unfinished)
This commit is contained in:
		
							parent
							
								
									94311e187f
								
							
						
					
					
						commit
						be0ba9ea88
					
				| @ -9,4 +9,4 @@ DB_TYPE = mysql | ||||
| HOST =  | ||||
| NAME = gogs | ||||
| USER = root | ||||
| PASSWD = root | ||||
| PASSWD =  | ||||
|  | ||||
							
								
								
									
										65
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								gogs.go
									
									
									
									
									
								
							| @ -1,44 +1,49 @@ | ||||
| // 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.
 | ||||
| // Copyright 2013-2014 gogs authors.
 | ||||
| //
 | ||||
| // 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 | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	"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" | ||||
| 	"github.com/codegangsta/cli" | ||||
| ) | ||||
| 
 | ||||
| // +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" | ||||
| 
 | ||||
| func init() { | ||||
| 
 | ||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	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) | ||||
| 	app := cli.NewApp() | ||||
| 	app.Name = "gogs" | ||||
| 	app.Usage = "Go Git Service" | ||||
| 	app.Version = APP_VER | ||||
| 	app.Commands = []cli.Command{ | ||||
| 		CmdWeb, | ||||
| 		CmdServ, | ||||
| 	} | ||||
| 	app.Flags = append(app.Flags, []cli.Flag{ | ||||
| 		cli.BoolFlag{"noterm", "disable color output"}, | ||||
| 	}...) | ||||
| 	app.Run(os.Args) | ||||
| } | ||||
|  | ||||
| @ -17,7 +17,7 @@ import ( | ||||
| 
 | ||||
| var ( | ||||
| 	orm          *xorm.Engine | ||||
| 	repoRootPath string | ||||
| 	RepoRootPath string | ||||
| ) | ||||
| 
 | ||||
| type Members struct { | ||||
| @ -71,5 +71,9 @@ func setEngine() { | ||||
| 
 | ||||
| func init() { | ||||
| 	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
 | ||||
| func IsRepositoryExist(user *User, reposName string) (bool, error) { | ||||
| 	repo := Repo{OwnerId: user.Id} | ||||
| 	// TODO: get repository by nocase name
 | ||||
| 	return orm.Where("lower_name = ?", strings.ToLower(reposName)).Get(&repo) | ||||
| 	has, err := 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
 | ||||
| //
 | ||||
| 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) | ||||
| 	f := filepath.Join(p, reposName+".git") | ||||
| 	_, err := git.InitRepository(f, false) | ||||
| @ -108,7 +115,7 @@ func DeleteRepository(user *User, reposName string) (err error) { | ||||
| 		session.Rollback() | ||||
| 		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
 | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @ -123,6 +123,19 @@ func (user *User) EncodePasswd() error { | ||||
| 	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.
 | ||||
| func LoginUserPlain(name, passwd string) (*User, error) { | ||||
| 	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 ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/Unknwon/goconfig" | ||||
| ) | ||||
| 
 | ||||
| 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() { | ||||
| 	var err error | ||||
| 	Cfg, err = goconfig.LoadConfigFile("conf/app.ini") | ||||
| 	workDir, err := exeDir() | ||||
| 	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) | ||||
| 	} | ||||
| 	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 New Issue
	
	Block a user