// 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) } }