0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
|
// Copyright (C) 2025, Jakob Wakeling
// All rights reserved.
package main
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/Jamozed/Goit/src/goit"
"github.com/Jamozed/Goit/src/util"
_ "github.com/mattn/go-sqlite3"
)
func main() {
if len(os.Args) < 2 || os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
fmt.Fprint(os.Stderr, "Interactive Goit shell is not enabled.\n")
os.Exit(-1)
}
username := os.Args[1]
soc := os.Getenv("SSH_ORIGINAL_COMMAND")
/* Parse the SSH_ORIGINAL_COMMAND value for the direction and repository name. */
re := regexp.MustCompile(`^(git-upload-pack|git-receive-pack|git-upload-archive) '?/?(.*?)'?$`)
matches := re.FindStringSubmatch(soc)
if len(matches) != 3 || matches[1] == "" {
fmt.Fprintln(os.Stderr, "Unknown command:", soc)
os.Exit(-1)
}
command := matches[1]
action := util.If(strings.Contains(command, "upload"), "r", "w")
reponame := strings.TrimSuffix(strings.TrimSuffix(matches[2], "/"), ".git")
if !goit.IsLegal(reponame) {
fmt.Fprintln(os.Stderr, "Repository not found.")
os.Exit(-1)
}
/* Load the config. */
conf, err := goit.LoadConfig()
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to load config:", err.Error())
os.Exit(-1)
}
/* Open the database. */
db, err := sql.Open("sqlite3", filepath.Join(conf.DataPath, "goit.db?_timeout=5000"))
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to open database:", err.Error())
os.Exit(-1)
}
defer db.Close()
/* Set global config and database variables correctly. */
goit.Conf = conf
goit.ShellSetDB(db)
/* Confirm that the database is the expected version. */
var version int
if err := db.QueryRow("PRAGMA user_version").Scan(&version); err != nil {
fmt.Fprintln(os.Stderr, "Failed to get database version:", err.Error())
os.Exit(-1)
}
if version != goit.LATEST_VERSION {
fmt.Fprintln(os.Stderr, "Unexpected database version.")
os.Exit(-1)
}
/* Confirm that the user exists and is enabled. */
user, err := goit.GetUserByName(username)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to get user:", err.Error())
os.Exit(-1)
}
if user == nil {
fmt.Fprintln(os.Stderr, "User not found.")
os.Exit(-1)
}
/* Confirm that the repository exists. */
repo, err := goit.GetRepoByName(reponame)
if err != nil {
fmt.Fprintln(os.Stderr, "Failed to get repository:", err.Error())
os.Exit(-1)
}
/* Check user authorization against repository. */
if repo == nil || (repo.Visibility == goit.Private && user.Id != repo.OwnerId) {
fmt.Fprintln(os.Stderr, "Repository not found.")
os.Exit(-1)
}
/* Check if user has write permissions for the repository, if required. */
if action == "w" && repo.OwnerId != user.Id {
fmt.Fprintln(os.Stderr, "Write access denied.")
os.Exit(-1)
}
/* Run git-shell command. */
if _, _, err := goit.NewGitCommand(
"shell", "-c", command+" '"+goit.RepoPath(reponame, true)+"'",
).Run(os.Stdin, os.Stdout); err != nil {
os.Exit(-1)
}
}
|