Merge branch 'access' of github.com:gogits/gogs into dev

This commit is contained in:
Unknwon 2015-02-28 22:25:10 -05:00
commit a6a2f59d1d
3 changed files with 54 additions and 85 deletions

View file

@ -21,6 +21,10 @@ import (
"github.com/gogits/gogs/modules/uuid" "github.com/gogits/gogs/modules/uuid"
) )
const (
_ACCESS_DENIED_MESSAGE = "Repository does not exist or you do not have access"
)
var CmdServ = cli.Command{ var CmdServ = cli.Command{
Name: "serv", Name: "serv",
Usage: "This command should only be called by SSH shell", Usage: "This command should only be called by SSH shell",
@ -55,68 +59,55 @@ func parseCmd(cmd string) (string, string) {
if len(ss) != 2 { if len(ss) != 2 {
return "", "" return "", ""
} }
return ss[0], strings.Replace(ss[1], "'/", "'", 1)
verb, args := ss[0], ss[1]
if verb == "git" {
ss = strings.SplitN(args, " ", 2)
args = ss[1]
verb = fmt.Sprintf("%s %s", verb, ss[0])
}
return verb, strings.Replace(args, "'/", "'", 1)
} }
var ( var (
COMMANDS_READONLY = map[string]models.AccessMode{ COMMANDS = map[string]models.AccessMode{
"git-upload-pack": models.ACCESS_MODE_WRITE, "git-upload-pack": models.ACCESS_MODE_READ,
"git upload-pack": models.ACCESS_MODE_WRITE, "git upload-pack": models.ACCESS_MODE_READ,
"git-upload-archive": models.ACCESS_MODE_WRITE, "git-upload-archive": models.ACCESS_MODE_READ,
} "git-receive-pack": models.ACCESS_MODE_WRITE,
"git receive-pack": models.ACCESS_MODE_WRITE,
COMMANDS_WRITE = map[string]models.AccessMode{
"git-receive-pack": models.ACCESS_MODE_READ,
"git receive-pack": models.ACCESS_MODE_READ,
} }
) )
func In(b string, sl map[string]models.AccessMode) bool {
_, e := sl[b]
return e
}
func runServ(c *cli.Context) { func runServ(c *cli.Context) {
if c.IsSet("config") { if c.IsSet("config") {
setting.CustomConf = c.String("config") setting.CustomConf = c.String("config")
} }
setup("serv.log") setup("serv.log")
if len(c.Args()) < 1 { fail := func(userMessage, logMessage string, args ...interface{}) {
log.GitLogger.Fatal(2, "Not enough arguments") fmt.Fprintln(os.Stderr, "Gogs: ", userMessage)
log.GitLogger.Fatal(2, logMessage, args...)
} }
if len(c.Args()) < 1 {
fail("Not enough arguments", "Not enough arugments")
}
keys := strings.Split(c.Args()[0], "-") keys := strings.Split(c.Args()[0], "-")
if len(keys) != 2 { if len(keys) != 2 {
println("Gogs: auth file format error") fail("key-id format error", "Invalid key id: %s", c.Args()[0])
log.GitLogger.Fatal(2, "Invalid auth file format: %s", os.Args[2])
} }
keyId, err := com.StrTo(keys[1]).Int64() keyId, err := com.StrTo(keys[1]).Int64()
if err != nil { if err != nil {
println("Gogs: auth file format error") fail("key-id format error", "Invalid key id: %s", err)
log.GitLogger.Fatal(2, "Invalid auth file format: %v", err)
} }
user, err := models.GetUserByKeyId(keyId) user, err := models.GetUserByKeyId(keyId)
if err != nil { if err != nil {
if err == models.ErrUserNotKeyOwner { fail("internal error", "Fail to get user by key ID(%d): %v", keyId, err)
println("Gogs: you are not the owner of SSH key")
log.GitLogger.Fatal(2, "Invalid owner of SSH key: %d", keyId)
}
println("Gogs: internal error:", err.Error())
log.GitLogger.Fatal(2, "Fail to get user by key ID(%d): %v", keyId, err)
} }
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.") if user.IsAdmin {
println("If this is unexpected, please log in with password and setup Gogs under another user.")
}
return return
} }
@ -124,67 +115,47 @@ func runServ(c *cli.Context) {
repoPath := strings.Trim(args, "'") repoPath := strings.Trim(args, "'")
rr := strings.SplitN(repoPath, "/", 2) rr := strings.SplitN(repoPath, "/", 2)
if len(rr) != 2 { if len(rr) != 2 {
println("Gogs: unavailable repository", args) fail("Invalid repository path", "Invalide repository path: %v", args)
log.GitLogger.Fatal(2, "Unavailable repository: %v", args)
} }
repoUserName := rr[0] repoUserName := rr[0]
repoName := strings.TrimSuffix(rr[1], ".git") repoName := strings.TrimSuffix(rr[1], ".git")
isWrite := In(verb, COMMANDS_WRITE)
isRead := In(verb, COMMANDS_READONLY)
repoUser, err := models.GetUserByName(repoUserName) repoUser, err := models.GetUserByName(repoUserName)
if err != nil { if err != nil {
if err == models.ErrUserNotExist { if err == models.ErrUserNotExist {
println("Gogs: given repository owner are not registered") fail("Repository owner does not exist", "Unregistered owner: %s", repoUserName)
log.GitLogger.Fatal(2, "Unregistered owner: %s", repoUserName)
} }
println("Gogs: internal error:", err.Error()) fail("Internal error", "Fail to get repository owner(%s): %v", repoUserName, err)
log.GitLogger.Fatal(2, "Fail to get repository owner(%s): %v", repoUserName, err)
} }
// Access check.
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 {
println("Gogs: given repository does not exist") if user.Id == repoUser.Id || repoUser.IsOwnedBy(user.Id) {
log.GitLogger.Fatal(2, "Repository does not exist: %s/%s", repoUser.Name, repoName) fail("Repository does not exist", "Repository does not exist: %s/%s", repoUser.Name, repoName)
} else {
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, repoName)
}
} }
println("Gogs: internal error:", err.Error()) fail("Internal error", "Fail to get repository: %v", err)
log.GitLogger.Fatal(2, "Fail to get repository: %v", err)
} }
switch { requestedMode, has := COMMANDS[verb]
case isWrite: if !has {
has, err := models.HasAccess(user, repo, models.ACCESS_MODE_WRITE) fail("Unknown git command", "Unknown git command %s", verb)
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 { mode, err := models.AccessLevel(user, repo)
println("You can't write to a mirror repository") if err != nil {
log.GitLogger.Fatal(2, "User %s tried to write to a mirror repository %s", user.Name, repoPath) fail("Internal error", "Fail to check access: %v", err)
} else if mode < requestedMode {
clientMessage := _ACCESS_DENIED_MESSAGE
if mode >= models.ACCESS_MODE_READ {
clientMessage = "You do not have sufficient authorization for this action"
} }
case isRead: fail(clientMessage,
if !repo.IsPrivate { "User %s does not have level %v access to repository %s",
break user.Name, requestedMode, repoPath)
}
has, err := models.HasAccess(user, repo, models.ACCESS_MODE_READ)
if err != nil {
println("Gogs: internal error:", err.Error())
log.GitLogger.Fatal(2, "Fail to check read access:", err)
} else if !has {
println("You have no right to access this repository")
log.GitLogger.Fatal(2, "User %s has no right to read repository %s", user.Name, repoPath)
}
default:
println("Unknown command: " + cmd)
return
} }
uuid := uuid.NewV4().String() uuid := uuid.NewV4().String()
@ -202,11 +173,10 @@ func runServ(c *cli.Context) {
gitcmd.Stdin = os.Stdin gitcmd.Stdin = os.Stdin
gitcmd.Stderr = os.Stderr gitcmd.Stderr = os.Stderr
if err = gitcmd.Run(); err != nil { if err = gitcmd.Run(); err != nil {
println("Gogs: internal error:", err.Error()) fail("Internal error", "Fail to execute git command: %v", err)
log.GitLogger.Fatal(2, "Fail to execute git command: %v", err)
} }
if isWrite { if requestedMode == models.ACCESS_MODE_WRITE {
tasks, err := models.GetUpdateTasksByUuid(uuid) tasks, err := models.GetUpdateTasksByUuid(uuid)
if err != nil { if err != nil {
log.GitLogger.Fatal(2, "GetUpdateTasksByUuid: %v", err) log.GitLogger.Fatal(2, "GetUpdateTasksByUuid: %v", err)
@ -228,10 +198,10 @@ func runServ(c *cli.Context) {
// Update key activity. // Update key activity.
key, err := models.GetPublicKeyById(keyId) key, err := models.GetPublicKeyById(keyId)
if err != nil { if err != nil {
log.GitLogger.Fatal(2, "GetPublicKeyById: %v", err) fail("Internal error", "GetPublicKeyById: %v", err)
} }
key.Updated = time.Now() key.Updated = time.Now()
if err = models.UpdatePublicKey(key); err != nil { if err = models.UpdatePublicKey(key); err != nil {
log.GitLogger.Fatal(2, "UpdatePublicKey: %v", err) fail("Internal error", "UpdatePublicKey: %v", err)
} }
} }

View file

@ -149,7 +149,7 @@ repo_name_been_taken = Repository name has been already taken.
org_name_been_taken = Organization name has been already taken. org_name_been_taken = Organization name has been already taken.
team_name_been_taken = Team name has been already taken. team_name_been_taken = Team name has been already taken.
email_been_used = E-mail address has been already used. email_been_used = E-mail address has been already used.
ssh_key_been_used = Public key name has been used. ssh_key_been_used = Public key name or content has been used.
illegal_username = Your username contains illegal characters. illegal_username = Your username contains illegal characters.
illegal_repo_name = Repository name contains illegal characters. illegal_repo_name = Repository name contains illegal characters.
illegal_org_name = Organization name contains illegal characters. illegal_org_name = Organization name contains illegal characters.

View file

@ -130,7 +130,6 @@ func extractTypeFromBase64Key(key string) (string, error) {
// Parse any key string in openssh or ssh2 format to clean openssh string (rfc4253) // Parse any key string in openssh or ssh2 format to clean openssh string (rfc4253)
func ParseKeyString(content string) (string, error) { func ParseKeyString(content string) (string, error) {
// Transform all legal line endings to a single "\n" // Transform all legal line endings to a single "\n"
s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1) s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1)